#ifndef THINK_THINK_DB_QUERY_H
#define THINK_THINK_DB_QUERY_H

static char* think_db_query =
	"\n"
	"// +----------------------------------------------------------------------\n"
	"// | ThinkPHP [ WE CAN DO IT JUST THINK ]\n"
	"// +----------------------------------------------------------------------\n"
	"// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.\n"
	"// +----------------------------------------------------------------------\n"
	"// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )\n"
	"// +----------------------------------------------------------------------\n"
	"// | Author: liu21st <liu21st@gmail.com>\n"
	"// +----------------------------------------------------------------------\n"
	"\n"
	"namespace think\\db;\n"
	"\n"
	"use PDO;\n"
	"use think\\App;\n"
	"use think\\Cache;\n"
	"use think\\Collection;\n"
	"use think\\Config;\n"
	"use think\\Db;\n"
	"use think\\db\\exception\\BindParamException;\n"
	"use think\\db\\exception\\DataNotFoundException;\n"
	"use think\\db\\exception\\ModelNotFoundException;\n"
	"use think\\Exception;\n"
	"use think\\exception\\DbException;\n"
	"use think\\exception\\PDOException;\n"
	"use think\\Loader;\n"
	"use think\\Model;\n"
	"use think\\model\\Relation;\n"
	"use think\\model\\relation\\OneToOne;\n"
	"use think\\Paginator;\n"
	"\n"
	"class Query\n"
	"{\n"
	"    // 数据库Connection对象实例\n"
	"    protected $connection;\n"
	"    // 数据库Builder对象实例\n"
	"    protected $builder;\n"
	"    // 当前模型类名称\n"
	"    protected $model;\n"
	"    // 当前数据表名称（含前缀）\n"
	"    protected $table = \'\';\n"
	"    // 当前数据表名称（不含前缀）\n"
	"    protected $name = \'\';\n"
	"    // 当前数据表主键\n"
	"    protected $pk;\n"
	"    // 当前数据表前缀\n"
	"    protected $prefix = \'\';\n"
	"    // 查询参数\n"
	"    protected $options = [];\n"
	"    // 参数绑定\n"
	"    protected $bind = [];\n"
	"    // 数据表信息\n"
	"    protected static $info = [];\n"
	"    // 回调事件\n"
	"    private static $event = [];\n"
	"    // 读取主库\n"
	"    protected static $readMaster = [];\n"
	"\n"
	"    /**\n"
	"     * 构造函数\n"
	"     * @access public\n"
	"     * @param Connection $connection 数据库对象实例\n"
	"     * @param Model      $model      模型对象\n"
	"     */\n"
	"    public function __construct(Connection $connection = null, $model = null)\n"
	"    {\n"
	"        $this->connection = $connection ?: Db::connect([], true);\n"
	"        $this->prefix     = $this->connection->getConfig(\'prefix\');\n"
	"        $this->model      = $model;\n"
	"        // 设置当前连接的Builder对象\n"
	"        $this->setBuilder();\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 利用__call方法实现一些特殊的Model方法\n"
	"     * @access public\n"
	"     * @param string $method 方法名称\n"
	"     * @param array  $args   调用参数\n"
	"     * @return mixed\n"
	"     * @throws DbException\n"
	"     * @throws Exception\n"
	"     */\n"
	"    public function __call($method, $args)\n"
	"    {\n"
	"        if (strtolower(substr($method, 0, 5)) == \'getby\') {\n"
	"            // 根据某个字段获取记录\n"
	"            $field         = Loader::parseName(substr($method, 5));\n"
	"            $where[$field] = $args[0];\n"
	"            return $this->where($where)->find();\n"
	"        } elseif (strtolower(substr($method, 0, 10)) == \'getfieldby\') {\n"
	"            // 根据某个字段获取记录的某个值\n"
	"            $name         = Loader::parseName(substr($method, 10));\n"
	"            $where[$name] = $args[0];\n"
	"            return $this->where($where)->value($args[1]);\n"
	"        } elseif ($this->model && method_exists($this->model, \'scope\' . $method)) {\n"
	"            // 动态调用命名范围\n"
	"            $method = \'scope\' . $method;\n"
	"            array_unshift($args, $this);\n"
	"\n"
	"            call_user_func_array([$this->model, $method], $args);\n"
	"            return $this;\n"
	"        } else {\n"
	"            throw new Exception(\'method not exist:\' . __CLASS__ . \'->\' . $method);\n"
	"        }\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 获取当前的数据库Connection对象\n"
	"     * @access public\n"
	"     * @return Connection\n"
	"     */\n"
	"    public function getConnection()\n"
	"    {\n"
	"        return $this->connection;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 切换当前的数据库连接\n"
	"     * @access public\n"
	"     * @param mixed $config\n"
	"     * @return $this\n"
	"     */\n"
	"    public function connect($config)\n"
	"    {\n"
	"        $this->connection = Db::connect($config);\n"
	"        $this->setBuilder();\n"
	"        $this->prefix = $this->connection->getConfig(\'prefix\');\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 设置当前的数据库Builder对象\n"
	"     * @access protected\n"
	"     * @return void\n"
	"     */\n"
	"    protected function setBuilder()\n"
	"    {\n"
	"        $class         = $this->connection->getBuilder();\n"
	"        $this->builder = new $class($this->connection, $this);\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 获取当前的模型对象实例\n"
	"     * @access public\n"
	"     * @return Model|null\n"
	"     */\n"
	"    public function getModel()\n"
	"    {\n"
	"        return $this->model;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 设置后续从主库读取数据\n"
	"     * @access public\n"
	"     * @param  bool $allTable\n"
	"     * @return void\n"
	"     */\n"
	"    public function readMaster($allTable = false)\n"
	"    {\n"
	"        if ($allTable) {\n"
	"            $table = \'*\';\n"
	"        } else {\n"
	"            $table = isset($this->options[\'table\']) ? $this->options[\'table\'] : $this->getTable();\n"
	"        }\n"
	"\n"
	"        static::$readMaster[$table] = true;\n"
	"\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 获取当前的builder实例对象\n"
	"     * @access public\n"
	"     * @return Builder\n"
	"     */\n"
	"    public function getBuilder()\n"
	"    {\n"
	"        return $this->builder;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 指定默认的数据表名（不含前缀）\n"
	"     * @access public\n"
	"     * @param string $name\n"
	"     * @return $this\n"
	"     */\n"
	"    public function name($name)\n"
	"    {\n"
	"        $this->name = $name;\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 指定默认数据表名（含前缀）\n"
	"     * @access public\n"
	"     * @param string $table 表名\n"
	"     * @return $this\n"
	"     */\n"
	"    public function setTable($table)\n"
	"    {\n"
	"        $this->table = $table;\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 得到当前或者指定名称的数据表\n"
	"     * @access public\n"
	"     * @param string $name\n"
	"     * @return string\n"
	"     */\n"
	"    public function getTable($name = \'\')\n"
	"    {\n"
	"        if ($name || empty($this->table)) {\n"
	"            $name      = $name ?: $this->name;\n"
	"            $tableName = $this->prefix;\n"
	"            if ($name) {\n"
	"                $tableName .= Loader::parseName($name);\n"
	"            }\n"
	"        } else {\n"
	"            $tableName = $this->table;\n"
	"        }\n"
	"        return $tableName;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 将SQL语句中的__TABLE_NAME__字符串替换成带前缀的表名（小写）\n"
	"     * @access public\n"
	"     * @param string $sql sql语句\n"
	"     * @return string\n"
	"     */\n"
	"    public function parseSqlTable($sql)\n"
	"    {\n"
	"        if (false !== strpos($sql, \'__\')) {\n"
	"            $prefix = $this->prefix;\n"
	"            $sql    = preg_replace_callback(\"/__([A-Z0-9_-]+)__/sU\", function ($match) use ($prefix) {\n"
	"                return $prefix . strtolower($match[1]);\n"
	"            }, $sql);\n"
	"        }\n"
	"        return $sql;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 执行查询 返回数据集\n"
	"     * @access public\n"
	"     * @param string      $sql    sql指令\n"
	"     * @param array       $bind   参数绑定\n"
	"     * @param boolean     $master 是否在主服务器读操作\n"
	"     * @param bool|string $class  指定返回的数据集对象\n"
	"     * @return mixed\n"
	"     * @throws BindParamException\n"
	"     * @throws PDOException\n"
	"     */\n"
	"    public function query($sql, $bind = [], $master = false, $class = false)\n"
	"    {\n"
	"        return $this->connection->query($sql, $bind, $master, $class);\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 执行语句\n"
	"     * @access public\n"
	"     * @param string $sql  sql指令\n"
	"     * @param array  $bind 参数绑定\n"
	"     * @return int\n"
	"     * @throws BindParamException\n"
	"     * @throws PDOException\n"
	"     */\n"
	"    public function execute($sql, $bind = [])\n"
	"    {\n"
	"        return $this->connection->execute($sql, $bind, $this);\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 获取最近插入的ID\n"
	"     * @access public\n"
	"     * @param string $sequence 自增序列名\n"
	"     * @return string\n"
	"     */\n"
	"    public function getLastInsID($sequence = null)\n"
	"    {\n"
	"        return $this->connection->getLastInsID($sequence);\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 获取最近一次查询的sql语句\n"
	"     * @access public\n"
	"     * @return string\n"
	"     */\n"
	"    public function getLastSql()\n"
	"    {\n"
	"        return $this->connection->getLastSql();\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 执行数据库事务\n"
	"     * @access public\n"
	"     * @param callable $callback 数据操作方法回调\n"
	"     * @return mixed\n"
	"     */\n"
	"    public function transaction($callback)\n"
	"    {\n"
	"        return $this->connection->transaction($callback);\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 启动事务\n"
	"     * @access public\n"
	"     * @return void\n"
	"     */\n"
	"    public function startTrans()\n"
	"    {\n"
	"        $this->connection->startTrans();\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 用于非自动提交状态下面的查询提交\n"
	"     * @access public\n"
	"     * @return void\n"
	"     * @throws PDOException\n"
	"     */\n"
	"    public function commit()\n"
	"    {\n"
	"        $this->connection->commit();\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 事务回滚\n"
	"     * @access public\n"
	"     * @return void\n"
	"     * @throws PDOException\n"
	"     */\n"
	"    public function rollback()\n"
	"    {\n"
	"        $this->connection->rollback();\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 批处理执行SQL语句\n"
	"     * 批处理的指令都认为是execute操作\n"
	"     * @access public\n"
	"     * @param array $sql SQL批处理指令\n"
	"     * @return boolean\n"
	"     */\n"
	"    public function batchQuery($sql = [], $bind = [])\n"
	"    {\n"
	"        return $this->connection->batchQuery($sql, $bind);\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 获取数据库的配置参数\n"
	"     * @access public\n"
	"     * @param string $name 参数名称\n"
	"     * @return boolean\n"
	"     */\n"
	"    public function getConfig($name = \'\')\n"
	"    {\n"
	"        return $this->connection->getConfig($name);\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 得到分表的的数据表名\n"
	"     * @access public\n"
	"     * @param array  $data  操作的数据\n"
	"     * @param string $field 分表依据的字段\n"
	"     * @param array  $rule  分表规则\n"
	"     * @return string\n"
	"     */\n"
	"    public function getPartitionTableName($data, $field, $rule = [])\n"
	"    {\n"
	"        // 对数据表进行分区\n"
	"        if ($field && isset($data[$field])) {\n"
	"            $value = $data[$field];\n"
	"            $type  = $rule[\'type\'];\n"
	"            switch ($type) {\n"
	"                case \'id\':\n"
	"                    // 按照id范围分表\n"
	"                    $step = $rule[\'expr\'];\n"
	"                    $seq  = floor($value / $step) + 1;\n"
	"                    break;\n"
	"                case \'year\':\n"
	"                    // 按照年份分表\n"
	"                    if (!is_numeric($value)) {\n"
	"                        $value = strtotime($value);\n"
	"                    }\n"
	"                    $seq = date(\'Y\', $value) - $rule[\'expr\'] + 1;\n"
	"                    break;\n"
	"                case \'mod\':\n"
	"                    // 按照id的模数分表\n"
	"                    $seq = ($value % $rule[\'num\']) + 1;\n"
	"                    break;\n"
	"                case \'md5\':\n"
	"                    // 按照md5的序列分表\n"
	"                    $seq = (ord(substr(md5($value), 0, 1)) % $rule[\'num\']) + 1;\n"
	"                    break;\n"
	"                default:\n"
	"                    if (function_exists($type)) {\n"
	"                        // 支持指定函数哈希\n"
	"                        $seq = (ord(substr($type($value), 0, 1)) % $rule[\'num\']) + 1;\n"
	"                    } else {\n"
	"                        // 按照字段的首字母的值分表\n"
	"                        $seq = (ord($value{0}) % $rule[\'num\']) + 1;\n"
	"                    }\n"
	"            }\n"
	"            return $this->getTable() . \'_\' . $seq;\n"
	"        } else {\n"
	"            // 当设置的分表字段不在查询条件或者数据中\n"
	"            // 进行联合查询，必须设定 partition[\'num\']\n"
	"            $tableName = [];\n"
	"            for ($i = 0; $i < $rule[\'num\']; $i++) {\n"
	"                $tableName[] = \'SELECT * FROM \' . $this->getTable() . \'_\' . ($i + 1);\n"
	"            }\n"
	"\n"
	"            $tableName = \'( \' . implode(\" UNION \", $tableName) . \') AS \' . $this->name;\n"
	"            return $tableName;\n"
	"        }\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 得到某个字段的值\n"
	"     * @access public\n"
	"     * @param string $field   字段名\n"
	"     * @param mixed  $default 默认值\n"
	"     * @param bool   $force   强制转为数字类型\n"
	"     * @return mixed\n"
	"     */\n"
	"    public function value($field, $default = null, $force = false)\n"
	"    {\n"
	"        $result = false;\n"
	"        if (empty($this->options[\'fetch_sql\']) && !empty($this->options[\'cache\'])) {\n"
	"            // 判断查询缓存\n"
	"            $cache = $this->options[\'cache\'];\n"
	"            if (empty($this->options[\'table\'])) {\n"
	"                $this->options[\'table\'] = $this->getTable();\n"
	"            }\n"
	"            $key    = is_string($cache[\'key\']) ? $cache[\'key\'] : md5($this->connection->getConfig(\'database\') . \'.\' . $field . serialize($this->options) . serialize($this->bind));\n"
	"            $result = Cache::get($key);\n"
	"        }\n"
	"        if (false === $result) {\n"
	"            if (isset($this->options[\'field\'])) {\n"
	"                unset($this->options[\'field\']);\n"
	"            }\n"
	"            $pdo = $this->field($field)->limit(1)->getPdo();\n"
	"            if (is_string($pdo)) {\n"
	"                // 返回SQL语句\n"
	"                return $pdo;\n"
	"            }\n"
	"\n"
	"            $result = $pdo->fetchColumn();\n"
	"            if ($force) {\n"
	"                $result = (float) $result;\n"
	"            }\n"
	"\n"
	"            if (isset($cache) && false !== $result) {\n"
	"                // 缓存数据\n"
	"                $this->cacheData($key, $result, $cache);\n"
	"            }\n"
	"        } else {\n"
	"            // 清空查询条件\n"
	"            $this->options = [];\n"
	"        }\n"
	"        return false !== $result ? $result : $default;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 得到某个列的数组\n"
	"     * @access public\n"
	"     * @param string $field 字段名 多个字段用逗号分隔\n"
	"     * @param string $key   索引\n"
	"     * @return array\n"
	"     */\n"
	"    public function column($field, $key = \'\')\n"
	"    {\n"
	"        $result = false;\n"
	"        if (empty($this->options[\'fetch_sql\']) && !empty($this->options[\'cache\'])) {\n"
	"            // 判断查询缓存\n"
	"            $cache = $this->options[\'cache\'];\n"
	"            if (empty($this->options[\'table\'])) {\n"
	"                $this->options[\'table\'] = $this->getTable();\n"
	"            }\n"
	"            $guid   = is_string($cache[\'key\']) ? $cache[\'key\'] : md5($this->connection->getConfig(\'database\') . \'.\' . $field . serialize($this->options) . serialize($this->bind));\n"
	"            $result = Cache::get($guid);\n"
	"        }\n"
	"        if (false === $result) {\n"
	"            if (isset($this->options[\'field\'])) {\n"
	"                unset($this->options[\'field\']);\n"
	"            }\n"
	"            if (is_null($field)) {\n"
	"                $field = \'*\';\n"
	"            } elseif ($key && \'*\' != $field) {\n"
	"                $field = $key . \',\' . $field;\n"
	"            }\n"
	"            $pdo = $this->field($field)->getPdo();\n"
	"            if (is_string($pdo)) {\n"
	"                // 返回SQL语句\n"
	"                return $pdo;\n"
	"            }\n"
	"            if (1 == $pdo->columnCount()) {\n"
	"                $result = $pdo->fetchAll(PDO::FETCH_COLUMN);\n"
	"            } else {\n"
	"                $resultSet = $pdo->fetchAll(PDO::FETCH_ASSOC);\n"
	"                if ($resultSet) {\n"
	"                    $fields = array_keys($resultSet[0]);\n"
	"                    $count  = count($fields);\n"
	"                    $key1   = array_shift($fields);\n"
	"                    $key2   = $fields ? array_shift($fields) : \'\';\n"
	"                    $key    = $key ?: $key1;\n"
	"                    if (strpos($key, \'.\')) {\n"
	"                        list($alias, $key) = explode(\'.\', $key);\n"
	"                    }\n"
	"                    foreach ($resultSet as $val) {\n"
	"                        if ($count > 2) {\n"
	"                            $result[$val[$key]] = $val;\n"
	"                        } elseif (2 == $count) {\n"
	"                            $result[$val[$key]] = $val[$key2];\n"
	"                        } elseif (1 == $count) {\n"
	"                            $result[$val[$key]] = $val[$key1];\n"
	"                        }\n"
	"                    }\n"
	"                } else {\n"
	"                    $result = [];\n"
	"                }\n"
	"            }\n"
	"            if (isset($cache) && isset($guid)) {\n"
	"                // 缓存数据\n"
	"                $this->cacheData($guid, $result, $cache);\n"
	"            }\n"
	"        } else {\n"
	"            // 清空查询条件\n"
	"            $this->options = [];\n"
	"        }\n"
	"        return $result;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * COUNT查询\n"
	"     * @access public\n"
	"     * @param string $field 字段名\n"
	"     * @return integer|string\n"
	"     */\n"
	"    public function count($field = \'*\')\n"
	"    {\n"
	"        if (isset($this->options[\'group\'])) {\n"
	"            if (!preg_match(\'/^[\\w\\.\\*]+$/\', $field)) {\n"
	"                throw new Exception(\'not support data:\' . $field);\n"
	"            }\n"
	"            // 支持GROUP\n"
	"            $options = $this->getOptions();\n"
	"            $subSql  = $this->options($options)->field(\'count(\' . $field . \')\')->bind($this->bind)->buildSql();\n"
	"\n"
	"            $count = $this->table([$subSql => \'_group_count_\'])->value(\'COUNT(*) AS tp_count\', 0, true);\n"
	"        } else {\n"
	"            $count = $this->aggregate(\'COUNT\', $field, true);\n"
	"        }\n"
	"\n"
	"        return is_string($count) ? $count : (int) $count;\n"
	"\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 聚合查询\n"
	"     * @access public\n"
	"     * @param  string $aggregate    聚合方法\n"
	"     * @param  string $field        字段名\n"
	"     * @param  bool   $force        强制转为数字类型\n"
	"     * @return mixed\n"
	"     */\n"
	"    public function aggregate($aggregate, $field, $force = false)\n"
	"    {\n"
	"        if (0 === stripos($field, \'DISTINCT \')) {\n"
	"            list($distinct, $field) = explode(\' \', $field);\n"
	"        }\n"
	"\n"
	"        if (!preg_match(\'/^[\\w\\.\\+\\-\\*]+$/\', $field)) {\n"
	"            throw new Exception(\'not support data:\' . $field);\n"
	"        }\n"
	"\n"
	"        $result = $this->value($aggregate . \'(\' . (!empty($distinct) ? \'DISTINCT \' : \'\') . $field . \') AS tp_\' . strtolower($aggregate), 0, $force);\n"
	"\n"
	"        return $result;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * SUM查询\n"
	"     * @access public\n"
	"     * @param string $field 字段名\n"
	"     * @return float|int\n"
	"     */\n"
	"    public function sum($field)\n"
	"    {\n"
	"        return $this->aggregate(\'SUM\', $field, true);\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * MIN查询\n"
	"     * @access public\n"
	"     * @param string $field 字段名\n"
	"     * @param bool   $force   强制转为数字类型\n"
	"     * @return mixed\n"
	"     */\n"
	"    public function min($field, $force = true)\n"
	"    {\n"
	"        return $this->aggregate(\'MIN\', $field, $force);\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * MAX查询\n"
	"     * @access public\n"
	"     * @param string $field 字段名\n"
	"     * @param bool   $force   强制转为数字类型\n"
	"     * @return mixed\n"
	"     */\n"
	"    public function max($field, $force = true)\n"
	"    {\n"
	"        return $this->aggregate(\'MAX\', $field, $force);\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * AVG查询\n"
	"     * @access public\n"
	"     * @param string $field 字段名\n"
	"     * @return float|int\n"
	"     */\n"
	"    public function avg($field)\n"
	"    {\n"
	"        return $this->aggregate(\'AVG\', $field, true);\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 设置记录的某个字段值\n"
	"     * 支持使用数据库字段和方法\n"
	"     * @access public\n"
	"     * @param string|array $field 字段名\n"
	"     * @param mixed        $value 字段值\n"
	"     * @return integer\n"
	"     */\n"
	"    public function setField($field, $value = \'\')\n"
	"    {\n"
	"        if (is_array($field)) {\n"
	"            $data = $field;\n"
	"        } else {\n"
	"            $data[$field] = $value;\n"
	"        }\n"
	"        return $this->update($data);\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 字段值(延迟)增长\n"
	"     * @access public\n"
	"     * @param string  $field    字段名\n"
	"     * @param integer $step     增长值\n"
	"     * @param integer $lazyTime 延时时间(s)\n"
	"     * @return integer|true\n"
	"     * @throws Exception\n"
	"     */\n"
	"    public function setInc($field, $step = 1, $lazyTime = 0)\n"
	"    {\n"
	"        $condition = !empty($this->options[\'where\']) ? $this->options[\'where\'] : [];\n"
	"        if (empty($condition)) {\n"
	"            // 没有条件不做任何更新\n"
	"            throw new Exception(\'no data to update\');\n"
	"        }\n"
	"        if ($lazyTime > 0) {\n"
	"            // 延迟写入\n"
	"            $guid = md5($this->getTable() . \'_\' . $field . \'_\' . serialize($condition) . serialize($this->bind));\n"
	"            $step = $this->lazyWrite(\'inc\', $guid, $step, $lazyTime);\n"
	"            if (false === $step) {\n"
	"                // 清空查询条件\n"
	"                $this->options = [];\n"
	"                return true;\n"
	"            }\n"
	"        }\n"
	"        return $this->setField($field, [\'inc\', $step]);\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 字段值（延迟）减少\n"
	"     * @access public\n"
	"     * @param string  $field    字段名\n"
	"     * @param integer $step     减少值\n"
	"     * @param integer $lazyTime 延时时间(s)\n"
	"     * @return integer|true\n"
	"     * @throws Exception\n"
	"     */\n"
	"    public function setDec($field, $step = 1, $lazyTime = 0)\n"
	"    {\n"
	"        $condition = !empty($this->options[\'where\']) ? $this->options[\'where\'] : [];\n"
	"        if (empty($condition)) {\n"
	"            // 没有条件不做任何更新\n"
	"            throw new Exception(\'no data to update\');\n"
	"        }\n"
	"        if ($lazyTime > 0) {\n"
	"            // 延迟写入\n"
	"            $guid = md5($this->getTable() . \'_\' . $field . \'_\' . serialize($condition) . serialize($this->bind));\n"
	"            $step = $this->lazyWrite(\'dec\', $guid, $step, $lazyTime);\n"
	"            if (false === $step) {\n"
	"                // 清空查询条件\n"
	"                $this->options = [];\n"
	"                return true;\n"
	"            }\n"
	"            return $this->setField($field, [\'inc\', $step]);\n"
	"        }\n"
	"        return $this->setField($field, [\'dec\', $step]);\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 延时更新检查 返回false表示需要延时\n"
	"     * 否则返回实际写入的数值\n"
	"     * @access protected\n"
	"     * @param string  $type     自增或者自减\n"
	"     * @param string  $guid     写入标识\n"
	"     * @param integer $step     写入步进值\n"
	"     * @param integer $lazyTime 延时时间(s)\n"
	"     * @return false|integer\n"
	"     */\n"
	"    protected function lazyWrite($type, $guid, $step, $lazyTime)\n"
	"    {\n"
	"        if (!Cache::has($guid . \'_time\')) {\n"
	"            // 计时开始\n"
	"            Cache::set($guid . \'_time\', $_SERVER[\'REQUEST_TIME\'], 0);\n"
	"            Cache::$type($guid, $step);\n"
	"        } elseif ($_SERVER[\'REQUEST_TIME\'] > Cache::get($guid . \'_time\') + $lazyTime) {\n"
	"            // 删除缓存\n"
	"            $value = Cache::$type($guid, $step);\n"
	"            Cache::rm($guid);\n"
	"            Cache::rm($guid . \'_time\');\n"
	"            return 0 === $value ? false : $value;\n"
	"        } else {\n"
	"            // 更新缓存\n"
	"            Cache::$type($guid, $step);\n"
	"        }\n"
	"        return false;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 查询SQL组装 join\n"
	"     * @access public\n"
	"     * @param mixed  $join      关联的表名\n"
	"     * @param mixed  $condition 条件\n"
	"     * @param string $type      JOIN类型\n"
	"     * @return $this\n"
	"     */\n"
	"    public function join($join, $condition = null, $type = \'INNER\')\n"
	"    {\n"
	"        if (empty($condition)) {\n"
	"            // 如果为组数，则循环调用join\n"
	"            foreach ($join as $key => $value) {\n"
	"                if (is_array($value) && 2 <= count($value)) {\n"
	"                    $this->join($value[0], $value[1], isset($value[2]) ? $value[2] : $type);\n"
	"                }\n"
	"            }\n"
	"        } else {\n"
	"            $table = $this->getJoinTable($join);\n"
	"\n"
	"            $this->options[\'join\'][] = [$table, strtoupper($type), $condition];\n"
	"        }\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 获取Join表名及别名 支持\n"
	"     * [\'prefix_table或者子查询\'=>\'alias\'] \'prefix_table alias\' \'table alias\'\n"
	"     * @access public\n"
	"     * @param array|string $join\n"
	"     * @return array|string\n"
	"     */\n"
	"    protected function getJoinTable($join, &$alias = null)\n"
	"    {\n"
	"        // 传入的表名为数组\n"
	"        if (is_array($join)) {\n"
	"            $table = $join;\n"
	"            $alias = array_shift($join);\n"
	"        } else {\n"
	"            $join = trim($join);\n"
	"            if (false !== strpos($join, \'(\')) {\n"
	"                // 使用子查询\n"
	"                $table = $join;\n"
	"            } else {\n"
	"                $prefix = $this->prefix;\n"
	"                if (strpos($join, \' \')) {\n"
	"                    // 使用别名\n"
	"                    list($table, $alias) = explode(\' \', $join);\n"
	"                } else {\n"
	"                    $table = $join;\n"
	"                    if (false === strpos($join, \'.\') && 0 !== strpos($join, \'__\')) {\n"
	"                        $alias = $join;\n"
	"                    }\n"
	"                }\n"
	"                if ($prefix && false === strpos($table, \'.\') && 0 !== strpos($table, $prefix) && 0 !== strpos($table, \'__\')) {\n"
	"                    $table = $this->getTable($table);\n"
	"                }\n"
	"            }\n"
	"            if (isset($alias) && $table != $alias) {\n"
	"                $table = [$table => $alias];\n"
	"            }\n"
	"        }\n"
	"        return $table;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 查询SQL组装 union\n"
	"     * @access public\n"
	"     * @param mixed   $union\n"
	"     * @param boolean $all\n"
	"     * @return $this\n"
	"     */\n"
	"    public function union($union, $all = false)\n"
	"    {\n"
	"        $this->options[\'union\'][\'type\'] = $all ? \'UNION ALL\' : \'UNION\';\n"
	"\n"
	"        if (is_array($union)) {\n"
	"            $this->options[\'union\'] = array_merge($this->options[\'union\'], $union);\n"
	"        } else {\n"
	"            $this->options[\'union\'][] = $union;\n"
	"        }\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 指定查询字段 支持字段排除和指定数据表\n"
	"     * @access public\n"
	"     * @param mixed   $field\n"
	"     * @param boolean $except    是否排除\n"
	"     * @param string  $tableName 数据表名\n"
	"     * @param string  $prefix    字段前缀\n"
	"     * @param string  $alias     别名前缀\n"
	"     * @return $this\n"
	"     */\n"
	"    public function field($field, $except = false, $tableName = \'\', $prefix = \'\', $alias = \'\')\n"
	"    {\n"
	"        if (empty($field)) {\n"
	"            return $this;\n"
	"        } elseif ($field instanceof Expression) {\n"
	"            $this->options[\'field\'][] = $field;\n"
	"            return $this;\n"
	"        }\n"
	"\n"
	"        if (is_string($field)) {\n"
	"            if (preg_match(\'/[\\<\\\'\\\"\\(]/\', $field)) {\n"
	"                return $this->fieldRaw($field);\n"
	"            }\n"
	"            $field = array_map(\'trim\', explode(\',\', $field));\n"
	"        }\n"
	"        if (true === $field) {\n"
	"            // 获取全部字段\n"
	"            $fields = $this->getTableInfo($tableName ?: (isset($this->options[\'table\']) ? $this->options[\'table\'] : \'\'), \'fields\');\n"
	"            $field  = $fields ?: [\'*\'];\n"
	"        } elseif ($except) {\n"
	"            // 字段排除\n"
	"            $fields = $this->getTableInfo($tableName ?: (isset($this->options[\'table\']) ? $this->options[\'table\'] : \'\'), \'fields\');\n"
	"            $field  = $fields ? array_diff($fields, $field) : $field;\n"
	"        }\n"
	"        if ($tableName) {\n"
	"            // 添加统一的前缀\n"
	"            $prefix = $prefix ?: $tableName;\n"
	"            foreach ($field as $key => $val) {\n"
	"                if (is_numeric($key)) {\n"
	"                    $val = $prefix . \'.\' . $val . ($alias ? \' AS \' . $alias . $val : \'\');\n"
	"                }\n"
	"                $field[$key] = $val;\n"
	"            }\n"
	"        }\n"
	"\n"
	"        if (isset($this->options[\'field\'])) {\n"
	"            $field = array_merge((array) $this->options[\'field\'], $field);\n"
	"        }\n"
	"        $this->options[\'field\'] = array_unique($field);\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 表达式方式指定查询字段\n"
	"     * @access public\n"
	"     * @param  string $field    字段名\n"
	"     * @param  array  $bind     参数绑定\n"
	"     * @return $this\n"
	"     */\n"
	"    public function fieldRaw($field, array $bind = [])\n"
	"    {\n"
	"        $this->options[\'field\'][] = $this->raw($field);\n"
	"\n"
	"        if ($bind) {\n"
	"            $this->bind($bind);\n"
	"        }\n"
	"\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 设置数据\n"
	"     * @access public\n"
	"     * @param mixed $field 字段名或者数据\n"
	"     * @param mixed $value 字段值\n"
	"     * @return $this\n"
	"     */\n"
	"    public function data($field, $value = null)\n"
	"    {\n"
	"        if (is_array($field)) {\n"
	"            $this->options[\'data\'] = isset($this->options[\'data\']) ? array_merge($this->options[\'data\'], $field) : $field;\n"
	"        } else {\n"
	"            $this->options[\'data\'][$field] = $value;\n"
	"        }\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 字段值增长\n"
	"     * @access public\n"
	"     * @param string|array $field 字段名\n"
	"     * @param integer      $step  增长值\n"
	"     * @return $this\n"
	"     */\n"
	"    public function inc($field, $step = 1)\n"
	"    {\n"
	"        $fields = is_string($field) ? explode(\',\', $field) : $field;\n"
	"        foreach ($fields as $field) {\n"
	"            $this->data($field, [\'inc\', $step]);\n"
	"        }\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 字段值减少\n"
	"     * @access public\n"
	"     * @param string|array $field 字段名\n"
	"     * @param integer      $step  增长值\n"
	"     * @return $this\n"
	"     */\n"
	"    public function dec($field, $step = 1)\n"
	"    {\n"
	"        $fields = is_string($field) ? explode(\',\', $field) : $field;\n"
	"        foreach ($fields as $field) {\n"
	"            $this->data($field, [\'dec\', $step]);\n"
	"        }\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 使用表达式设置数据\n"
	"     * @access public\n"
	"     * @param string $field 字段名\n"
	"     * @param string $value 字段值\n"
	"     * @return $this\n"
	"     */\n"
	"    public function exp($field, $value)\n"
	"    {\n"
	"        $this->data($field, $this->raw($value));\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 使用表达式设置数据\n"
	"     * @access public\n"
	"     * @param  mixed $value 表达式\n"
	"     * @return Expression\n"
	"     */\n"
	"    public function raw($value)\n"
	"    {\n"
	"        return new Expression($value);\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 指定JOIN查询字段\n"
	"     * @access public\n"
	"     * @param string|array $table 数据表\n"
	"     * @param string|array $field 查询字段\n"
	"     * @param mixed        $on    JOIN条件\n"
	"     * @param string       $type  JOIN类型\n"
	"     * @return $this\n"
	"     */\n"
	"    public function view($join, $field = true, $on = null, $type = \'INNER\')\n"
	"    {\n"
	"        $this->options[\'view\'] = true;\n"
	"        if (is_array($join) && key($join) === 0) {\n"
	"            foreach ($join as $key => $val) {\n"
	"                $this->view($val[0], $val[1], isset($val[2]) ? $val[2] : null, isset($val[3]) ? $val[3] : \'INNER\');\n"
	"            }\n"
	"        } else {\n"
	"            $fields = [];\n"
	"            $table  = $this->getJoinTable($join, $alias);\n"
	"\n"
	"            if (true === $field) {\n"
	"                $fields = $alias . \'.*\';\n"
	"            } else {\n"
	"                if (is_string($field)) {\n"
	"                    $field = explode(\',\', $field);\n"
	"                }\n"
	"                foreach ($field as $key => $val) {\n"
	"                    if (is_numeric($key)) {\n"
	"                        $fields[]                   = $alias . \'.\' . $val;\n"
	"                        $this->options[\'map\'][$val] = $alias . \'.\' . $val;\n"
	"                    } else {\n"
	"                        if (preg_match(\'/[,=\\.\\\'\\\"\\(\\s]/\', $key)) {\n"
	"                            $name = $key;\n"
	"                        } else {\n"
	"                            $name = $alias . \'.\' . $key;\n"
	"                        }\n"
	"                        $fields[$name]              = $val;\n"
	"                        $this->options[\'map\'][$val] = $name;\n"
	"                    }\n"
	"                }\n"
	"            }\n"
	"            $this->field($fields);\n"
	"            if ($on) {\n"
	"                $this->join($table, $on, $type);\n"
	"            } else {\n"
	"                $this->table($table);\n"
	"            }\n"
	"        }\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 设置分表规则\n"
	"     * @access public\n"
	"     * @param array  $data  操作的数据\n"
	"     * @param string $field 分表依据的字段\n"
	"     * @param array  $rule  分表规则\n"
	"     * @return $this\n"
	"     */\n"
	"    public function partition($data, $field, $rule = [])\n"
	"    {\n"
	"        $this->options[\'table\'] = $this->getPartitionTableName($data, $field, $rule);\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 指定AND查询条件\n"
	"     * @access public\n"
	"     * @param mixed $field     查询字段\n"
	"     * @param mixed $op        查询表达式\n"
	"     * @param mixed $condition 查询条件\n"
	"     * @return $this\n"
	"     */\n"
	"    public function where($field, $op = null, $condition = null)\n"
	"    {\n"
	"        $param = func_get_args();\n"
	"        array_shift($param);\n"
	"        $this->parseWhereExp(\'AND\', $field, $op, $condition, $param);\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 指定OR查询条件\n"
	"     * @access public\n"
	"     * @param mixed $field     查询字段\n"
	"     * @param mixed $op        查询表达式\n"
	"     * @param mixed $condition 查询条件\n"
	"     * @return $this\n"
	"     */\n"
	"    public function whereOr($field, $op = null, $condition = null)\n"
	"    {\n"
	"        $param = func_get_args();\n"
	"        array_shift($param);\n"
	"        $this->parseWhereExp(\'OR\', $field, $op, $condition, $param);\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 指定XOR查询条件\n"
	"     * @access public\n"
	"     * @param mixed $field     查询字段\n"
	"     * @param mixed $op        查询表达式\n"
	"     * @param mixed $condition 查询条件\n"
	"     * @return $this\n"
	"     */\n"
	"    public function whereXor($field, $op = null, $condition = null)\n"
	"    {\n"
	"        $param = func_get_args();\n"
	"        array_shift($param);\n"
	"        $this->parseWhereExp(\'XOR\', $field, $op, $condition, $param);\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 指定表达式查询条件\n"
	"     * @access public\n"
	"     * @param  string $where  查询条件\n"
	"     * @param  array  $bind   参数绑定\n"
	"     * @param  string $logic  查询逻辑 and or xor\n"
	"     * @return $this\n"
	"     */\n"
	"    public function whereRaw($where, $bind = [], $logic = \'AND\')\n"
	"    {\n"
	"        $this->options[\'where\'][$logic][] = $this->raw($where);\n"
	"\n"
	"        if ($bind) {\n"
	"            $this->bind($bind);\n"
	"        }\n"
	"\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 指定表达式查询条件 OR\n"
	"     * @access public\n"
	"     * @param  string $where  查询条件\n"
	"     * @param  array  $bind   参数绑定\n"
	"     * @return $this\n"
	"     */\n"
	"    public function whereOrRaw($where, $bind = [])\n"
	"    {\n"
	"        return $this->whereRaw($where, $bind, \'OR\');\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 指定Null查询条件\n"
	"     * @access public\n"
	"     * @param mixed  $field 查询字段\n"
	"     * @param string $logic 查询逻辑 and or xor\n"
	"     * @return $this\n"
	"     */\n"
	"    public function whereNull($field, $logic = \'AND\')\n"
	"    {\n"
	"        $this->parseWhereExp($logic, $field, \'null\', null, [], true);\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 指定NotNull查询条件\n"
	"     * @access public\n"
	"     * @param mixed  $field 查询字段\n"
	"     * @param string $logic 查询逻辑 and or xor\n"
	"     * @return $this\n"
	"     */\n"
	"    public function whereNotNull($field, $logic = \'AND\')\n"
	"    {\n"
	"        $this->parseWhereExp($logic, $field, \'notnull\', null, [], true);\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 指定Exists查询条件\n"
	"     * @access public\n"
	"     * @param mixed  $condition 查询条件\n"
	"     * @param string $logic     查询逻辑 and or xor\n"
	"     * @return $this\n"
	"     */\n"
	"    public function whereExists($condition, $logic = \'AND\')\n"
	"    {\n"
	"        $this->options[\'where\'][strtoupper($logic)][] = [\'exists\', $condition];\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 指定NotExists查询条件\n"
	"     * @access public\n"
	"     * @param mixed  $condition 查询条件\n"
	"     * @param string $logic     查询逻辑 and or xor\n"
	"     * @return $this\n"
	"     */\n"
	"    public function whereNotExists($condition, $logic = \'AND\')\n"
	"    {\n"
	"        $this->options[\'where\'][strtoupper($logic)][] = [\'not exists\', $condition];\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 指定In查询条件\n"
	"     * @access public\n"
	"     * @param mixed  $field     查询字段\n"
	"     * @param mixed  $condition 查询条件\n"
	"     * @param string $logic     查询逻辑 and or xor\n"
	"     * @return $this\n"
	"     */\n"
	"    public function whereIn($field, $condition, $logic = \'AND\')\n"
	"    {\n"
	"        $this->parseWhereExp($logic, $field, \'in\', $condition, [], true);\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 指定NotIn查询条件\n"
	"     * @access public\n"
	"     * @param mixed  $field     查询字段\n"
	"     * @param mixed  $condition 查询条件\n"
	"     * @param string $logic     查询逻辑 and or xor\n"
	"     * @return $this\n"
	"     */\n"
	"    public function whereNotIn($field, $condition, $logic = \'AND\')\n"
	"    {\n"
	"        $this->parseWhereExp($logic, $field, \'not in\', $condition, [], true);\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 指定Like查询条件\n"
	"     * @access public\n"
	"     * @param mixed  $field     查询字段\n"
	"     * @param mixed  $condition 查询条件\n"
	"     * @param string $logic     查询逻辑 and or xor\n"
	"     * @return $this\n"
	"     */\n"
	"    public function whereLike($field, $condition, $logic = \'AND\')\n"
	"    {\n"
	"        $this->parseWhereExp($logic, $field, \'like\', $condition, [], true);\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 指定NotLike查询条件\n"
	"     * @access public\n"
	"     * @param mixed  $field     查询字段\n"
	"     * @param mixed  $condition 查询条件\n"
	"     * @param string $logic     查询逻辑 and or xor\n"
	"     * @return $this\n"
	"     */\n"
	"    public function whereNotLike($field, $condition, $logic = \'AND\')\n"
	"    {\n"
	"        $this->parseWhereExp($logic, $field, \'not like\', $condition, [], true);\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 指定Between查询条件\n"
	"     * @access public\n"
	"     * @param mixed  $field     查询字段\n"
	"     * @param mixed  $condition 查询条件\n"
	"     * @param string $logic     查询逻辑 and or xor\n"
	"     * @return $this\n"
	"     */\n"
	"    public function whereBetween($field, $condition, $logic = \'AND\')\n"
	"    {\n"
	"        $this->parseWhereExp($logic, $field, \'between\', $condition, [], true);\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 指定NotBetween查询条件\n"
	"     * @access public\n"
	"     * @param mixed  $field     查询字段\n"
	"     * @param mixed  $condition 查询条件\n"
	"     * @param string $logic     查询逻辑 and or xor\n"
	"     * @return $this\n"
	"     */\n"
	"    public function whereNotBetween($field, $condition, $logic = \'AND\')\n"
	"    {\n"
	"        $this->parseWhereExp($logic, $field, \'not between\', $condition, [], true);\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 指定Exp查询条件\n"
	"     * @access public\n"
	"     * @param mixed  $field     查询字段\n"
	"     * @param mixed  $condition 查询条件\n"
	"     * @param string $logic     查询逻辑 and or xor\n"
	"     * @return $this\n"
	"     */\n"
	"    public function whereExp($field, $condition, $logic = \'AND\')\n"
	"    {\n"
	"        $this->parseWhereExp($logic, $field, \'exp\', $this->raw($condition), [], true);\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 设置软删除字段及条件\n"
	"     * @access public\n"
	"     * @param false|string  $field     查询字段\n"
	"     * @param mixed         $condition 查询条件\n"
	"     * @return $this\n"
	"     */\n"
	"    public function useSoftDelete($field, $condition = null)\n"
	"    {\n"
	"        if ($field) {\n"
	"            $this->options[\'soft_delete\'] = [$field, $condition ?: [\'null\', \'\']];\n"
	"        }\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 分析查询表达式\n"
	"     * @access public\n"
	"     * @param string                $logic     查询逻辑 and or xor\n"
	"     * @param string|array|\\Closure $field     查询字段\n"
	"     * @param mixed                 $op        查询表达式\n"
	"     * @param mixed                 $condition 查询条件\n"
	"     * @param array                 $param     查询参数\n"
	"     * @param  bool                 $strict    严格模式\n"
	"     * @return void\n"
	"     */\n"
	"    protected function parseWhereExp($logic, $field, $op, $condition, $param = [], $strict = false)\n"
	"    {\n"
	"        $logic = strtoupper($logic);\n"
	"        if ($field instanceof \\Closure) {\n"
	"            $this->options[\'where\'][$logic][] = is_string($op) ? [$op, $field] : $field;\n"
	"            return;\n"
	"        }\n"
	"\n"
	"        if (is_string($field) && !empty($this->options[\'via\']) && !strpos($field, \'.\')) {\n"
	"            $field = $this->options[\'via\'] . \'.\' . $field;\n"
	"        }\n"
	"\n"
	"        if ($field instanceof Expression) {\n"
	"            return $this->whereRaw($field, is_array($op) ? $op : []);\n"
	"        } elseif ($strict) {\n"
	"            // 使用严格模式查询\n"
	"            $where[$field] = [$op, $condition];\n"
	"\n"
	"            // 记录一个字段多次查询条件\n"
	"            $this->options[\'multi\'][$logic][$field][] = $where[$field];\n"
	"        } elseif (is_string($field) && preg_match(\'/[,=\\>\\<\\\'\\\"\\(\\s]/\', $field)) {\n"
	"            $where[] = [\'exp\', $this->raw($field)];\n"
	"            if (is_array($op)) {\n"
	"                // 参数绑定\n"
	"                $this->bind($op);\n"
	"            }\n"
	"        } elseif (is_null($op) && is_null($condition)) {\n"
	"            if (is_array($field)) {\n"
	"                // 数组批量查询\n"
	"                $where = $field;\n"
	"                foreach ($where as $k => $val) {\n"
	"                    $this->options[\'multi\'][$logic][$k][] = $val;\n"
	"                }\n"
	"            } elseif ($field && is_string($field)) {\n"
	"                // 字符串查询\n"
	"                $where[$field]                            = [\'null\', \'\'];\n"
	"                $this->options[\'multi\'][$logic][$field][] = $where[$field];\n"
	"            }\n"
	"        } elseif (is_array($op)) {\n"
	"            $where[$field] = $param;\n"
	"        } elseif (in_array(strtolower($op), [\'null\', \'notnull\', \'not null\'])) {\n"
	"            // null查询\n"
	"            $where[$field] = [$op, \'\'];\n"
	"\n"
	"            $this->options[\'multi\'][$logic][$field][] = $where[$field];\n"
	"        } elseif (is_null($condition)) {\n"
	"            // 字段相等查询\n"
	"            $where[$field] = [\'eq\', $op];\n"
	"\n"
	"            $this->options[\'multi\'][$logic][$field][] = $where[$field];\n"
	"        } else {\n"
	"            if (\'exp\' == strtolower($op)) {\n"
	"                $where[$field] = [\'exp\', $this->raw($condition)];\n"
	"                // 参数绑定\n"
	"                if (isset($param[2]) && is_array($param[2])) {\n"
	"                    $this->bind($param[2]);\n"
	"                }\n"
	"            } else {\n"
	"                $where[$field] = [$op, $condition];\n"
	"            }\n"
	"            // 记录一个字段多次查询条件\n"
	"            $this->options[\'multi\'][$logic][$field][] = $where[$field];\n"
	"        }\n"
	"\n"
	"        if (!empty($where)) {\n"
	"            if (!isset($this->options[\'where\'][$logic])) {\n"
	"                $this->options[\'where\'][$logic] = [];\n"
	"            }\n"
	"            if (is_string($field) && $this->checkMultiField($field, $logic)) {\n"
	"                $where[$field] = $this->options[\'multi\'][$logic][$field];\n"
	"            } elseif (is_array($field)) {\n"
	"                foreach ($field as $key => $val) {\n"
	"                    if ($this->checkMultiField($key, $logic)) {\n"
	"                        $where[$key] = $this->options[\'multi\'][$logic][$key];\n"
	"                    }\n"
	"                }\n"
	"            }\n"
	"            $this->options[\'where\'][$logic] = array_merge($this->options[\'where\'][$logic], $where);\n"
	"        }\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 检查是否存在一个字段多次查询条件\n"
	"     * @access public\n"
	"     * @param string $field 查询字段\n"
	"     * @param string $logic 查询逻辑 and or xor\n"
	"     * @return bool\n"
	"     */\n"
	"    private function checkMultiField($field, $logic)\n"
	"    {\n"
	"        return isset($this->options[\'multi\'][$logic][$field]) && count($this->options[\'multi\'][$logic][$field]) > 1;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 去除某个查询条件\n"
	"     * @access public\n"
	"     * @param string $field 查询字段\n"
	"     * @param string $logic 查询逻辑 and or xor\n"
	"     * @return $this\n"
	"     */\n"
	"    public function removeWhereField($field, $logic = \'AND\')\n"
	"    {\n"
	"        $logic = strtoupper($logic);\n"
	"        if (isset($this->options[\'where\'][$logic][$field])) {\n"
	"            unset($this->options[\'where\'][$logic][$field]);\n"
	"            unset($this->options[\'multi\'][$logic][$field]);\n"
	"        }\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 去除查询参数\n"
	"     * @access public\n"
	"     * @param string|bool $option 参数名 true 表示去除所有参数\n"
	"     * @return $this\n"
	"     */\n"
	"    public function removeOption($option = true)\n"
	"    {\n"
	"        if (true === $option) {\n"
	"            $this->options = [];\n"
	"        } elseif (is_string($option) && isset($this->options[$option])) {\n"
	"            unset($this->options[$option]);\n"
	"        }\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 指定查询数量\n"
	"     * @access public\n"
	"     * @param mixed $offset 起始位置\n"
	"     * @param mixed $length 查询数量\n"
	"     * @return $this\n"
	"     */\n"
	"    public function limit($offset, $length = null)\n"
	"    {\n"
	"        if (is_null($length) && strpos($offset, \',\')) {\n"
	"            list($offset, $length) = explode(\',\', $offset);\n"
	"        }\n"
	"        $this->options[\'limit\'] = intval($offset) . ($length ? \',\' . intval($length) : \'\');\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 指定分页\n"
	"     * @access public\n"
	"     * @param mixed $page     页数\n"
	"     * @param mixed $listRows 每页数量\n"
	"     * @return $this\n"
	"     */\n"
	"    public function page($page, $listRows = null)\n"
	"    {\n"
	"        if (is_null($listRows) && strpos($page, \',\')) {\n"
	"            list($page, $listRows) = explode(\',\', $page);\n"
	"        }\n"
	"        $this->options[\'page\'] = [intval($page), intval($listRows)];\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 分页查询\n"
	"     * @param int|array $listRows 每页数量 数组表示配置参数\n"
	"     * @param int|bool  $simple   是否简洁模式或者总记录数\n"
	"     * @param array     $config   配置参数\n"
	"     *                            page:当前页,\n"
	"     *                            path:url路径,\n"
	"     *                            query:url额外参数,\n"
	"     *                            fragment:url锚点,\n"
	"     *                            var_page:分页变量,\n"
	"     *                            list_rows:每页数量\n"
	"     *                            type:分页类名\n"
	"     * @return \\think\\Paginator\n"
	"     * @throws DbException\n"
	"     */\n"
	"    public function paginate($listRows = null, $simple = false, $config = [])\n"
	"    {\n"
	"        if (is_int($simple)) {\n"
	"            $total  = $simple;\n"
	"            $simple = false;\n"
	"        }\n"
	"        if (is_array($listRows)) {\n"
	"            $config   = array_merge(Config::get(\'paginate\'), $listRows);\n"
	"            $listRows = $config[\'list_rows\'];\n"
	"        } else {\n"
	"            $config   = array_merge(Config::get(\'paginate\'), $config);\n"
	"            $listRows = $listRows ?: $config[\'list_rows\'];\n"
	"        }\n"
	"\n"
	"        /** @var Paginator $class */\n"
	"        $class = false !== strpos($config[\'type\'], \'\\\\\') ? $config[\'type\'] : \'\\\\think\\\\paginator\\\\driver\\\\\' . ucwords($config[\'type\']);\n"
	"        $page  = isset($config[\'page\']) ? (int) $config[\'page\'] : call_user_func([\n"
	"            $class,\n"
	"            \'getCurrentPage\',\n"
	"        ], $config[\'var_page\']);\n"
	"\n"
	"        $page = $page < 1 ? 1 : $page;\n"
	"\n"
	"        $config[\'path\'] = isset($config[\'path\']) ? $config[\'path\'] : call_user_func([$class, \'getCurrentPath\']);\n"
	"\n"
	"        if (!isset($total) && !$simple) {\n"
	"            $options = $this->getOptions();\n"
	"\n"
	"            unset($this->options[\'order\'], $this->options[\'limit\'], $this->options[\'page\'], $this->options[\'field\']);\n"
	"\n"
	"            $bind    = $this->bind;\n"
	"            $total   = $this->count();\n"
	"            $results = $this->options($options)->bind($bind)->page($page, $listRows)->select();\n"
	"        } elseif ($simple) {\n"
	"            $results = $this->limit(($page - 1) * $listRows, $listRows + 1)->select();\n"
	"            $total   = null;\n"
	"        } else {\n"
	"            $results = $this->page($page, $listRows)->select();\n"
	"        }\n"
	"        return $class::make($results, $listRows, $page, $total, $simple, $config);\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 指定当前操作的数据表\n"
	"     * @access public\n"
	"     * @param mixed $table 表名\n"
	"     * @return $this\n"
	"     */\n"
	"    public function table($table)\n"
	"    {\n"
	"        if (is_string($table)) {\n"
	"            if (strpos($table, \')\')) {\n"
	"                // 子查询\n"
	"            } elseif (strpos($table, \',\')) {\n"
	"                $tables = explode(\',\', $table);\n"
	"                $table  = [];\n"
	"                foreach ($tables as $item) {\n"
	"                    list($item, $alias) = explode(\' \', trim($item));\n"
	"                    if ($alias) {\n"
	"                        $this->alias([$item => $alias]);\n"
	"                        $table[$item] = $alias;\n"
	"                    } else {\n"
	"                        $table[] = $item;\n"
	"                    }\n"
	"                }\n"
	"            } elseif (strpos($table, \' \')) {\n"
	"                list($table, $alias) = explode(\' \', $table);\n"
	"\n"
	"                $table = [$table => $alias];\n"
	"                $this->alias($table);\n"
	"            }\n"
	"        } else {\n"
	"            $tables = $table;\n"
	"            $table  = [];\n"
	"            foreach ($tables as $key => $val) {\n"
	"                if (is_numeric($key)) {\n"
	"                    $table[] = $val;\n"
	"                } else {\n"
	"                    $this->alias([$key => $val]);\n"
	"                    $table[$key] = $val;\n"
	"                }\n"
	"            }\n"
	"        }\n"
	"        $this->options[\'table\'] = $table;\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * USING支持 用于多表删除\n"
	"     * @access public\n"
	"     * @param mixed $using\n"
	"     * @return $this\n"
	"     */\n"
	"    public function using($using)\n"
	"    {\n"
	"        $this->options[\'using\'] = $using;\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 指定排序 order(\'id\',\'desc\') 或者 order([\'id\'=>\'desc\',\'create_time\'=>\'desc\'])\n"
	"     * @access public\n"
	"     * @param string|array $field 排序字段\n"
	"     * @param string       $order 排序\n"
	"     * @return $this\n"
	"     */\n"
	"    public function order($field, $order = null)\n"
	"    {\n"
	"        if (empty($field)) {\n"
	"            return $this;\n"
	"        } elseif ($field instanceof Expression) {\n"
	"            $this->options[\'order\'][] = $field;\n"
	"            return $this;\n"
	"        }\n"
	"\n"
	"        if (is_string($field)) {\n"
	"            if (!empty($this->options[\'via\'])) {\n"
	"                $field = $this->options[\'via\'] . \'.\' . $field;\n"
	"            }\n"
	"            if (strpos($field, \',\')) {\n"
	"                $field = array_map(\'trim\', explode(\',\', $field));\n"
	"            } else {\n"
	"                $field = empty($order) ? $field : [$field => $order];\n"
	"            }\n"
	"        } elseif (!empty($this->options[\'via\'])) {\n"
	"            foreach ($field as $key => $val) {\n"
	"                if (is_numeric($key)) {\n"
	"                    $field[$key] = $this->options[\'via\'] . \'.\' . $val;\n"
	"                } else {\n"
	"                    $field[$this->options[\'via\'] . \'.\' . $key] = $val;\n"
	"                    unset($field[$key]);\n"
	"                }\n"
	"            }\n"
	"        }\n"
	"        if (!isset($this->options[\'order\'])) {\n"
	"            $this->options[\'order\'] = [];\n"
	"        }\n"
	"        if (is_array($field)) {\n"
	"            $this->options[\'order\'] = array_merge($this->options[\'order\'], $field);\n"
	"        } else {\n"
	"            $this->options[\'order\'][] = $field;\n"
	"        }\n"
	"\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 表达式方式指定Field排序\n"
	"     * @access public\n"
	"     * @param  string $field 排序字段\n"
	"     * @param  array  $bind  参数绑定\n"
	"     * @return $this\n"
	"     */\n"
	"    public function orderRaw($field, array $bind = [])\n"
	"    {\n"
	"        $this->options[\'order\'][] = $this->raw($field);\n"
	"\n"
	"        if ($bind) {\n"
	"            $this->bind($bind);\n"
	"        }\n"
	"\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 查询缓存\n"
	"     * @access public\n"
	"     * @param mixed             $key    缓存key\n"
	"     * @param integer|\\DateTime $expire 缓存有效期\n"
	"     * @param string            $tag    缓存标签\n"
	"     * @return $this\n"
	"     */\n"
	"    public function cache($key = true, $expire = null, $tag = null)\n"
	"    {\n"
	"        // 增加快捷调用方式 cache(10) 等同于 cache(true, 10)\n"
	"        if ($key instanceof \\DateTime || (is_numeric($key) && is_null($expire))) {\n"
	"            $expire = $key;\n"
	"            $key    = true;\n"
	"        }\n"
	"\n"
	"        if (false !== $key) {\n"
	"            $this->options[\'cache\'] = [\'key\' => $key, \'expire\' => $expire, \'tag\' => $tag];\n"
	"        }\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 指定group查询\n"
	"     * @access public\n"
	"     * @param string $group GROUP\n"
	"     * @return $this\n"
	"     */\n"
	"    public function group($group)\n"
	"    {\n"
	"        $this->options[\'group\'] = $group;\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 指定having查询\n"
	"     * @access public\n"
	"     * @param string $having having\n"
	"     * @return $this\n"
	"     */\n"
	"    public function having($having)\n"
	"    {\n"
	"        $this->options[\'having\'] = $having;\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 指定查询lock\n"
	"     * @access public\n"
	"     * @param bool|string $lock 是否lock\n"
	"     * @return $this\n"
	"     */\n"
	"    public function lock($lock = false)\n"
	"    {\n"
	"        $this->options[\'lock\']   = $lock;\n"
	"        $this->options[\'master\'] = true;\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 指定distinct查询\n"
	"     * @access public\n"
	"     * @param string $distinct 是否唯一\n"
	"     * @return $this\n"
	"     */\n"
	"    public function distinct($distinct)\n"
	"    {\n"
	"        $this->options[\'distinct\'] = $distinct;\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 指定数据表别名\n"
	"     * @access public\n"
	"     * @param mixed $alias 数据表别名\n"
	"     * @return $this\n"
	"     */\n"
	"    public function alias($alias)\n"
	"    {\n"
	"        if (is_array($alias)) {\n"
	"            foreach ($alias as $key => $val) {\n"
	"                if (false !== strpos($key, \'__\')) {\n"
	"                    $table = $this->parseSqlTable($key);\n"
	"                } else {\n"
	"                    $table = $key;\n"
	"                }\n"
	"                $this->options[\'alias\'][$table] = $val;\n"
	"            }\n"
	"        } else {\n"
	"            if (isset($this->options[\'table\'])) {\n"
	"                $table = is_array($this->options[\'table\']) ? key($this->options[\'table\']) : $this->options[\'table\'];\n"
	"                if (false !== strpos($table, \'__\')) {\n"
	"                    $table = $this->parseSqlTable($table);\n"
	"                }\n"
	"            } else {\n"
	"                $table = $this->getTable();\n"
	"            }\n"
	"\n"
	"            $this->options[\'alias\'][$table] = $alias;\n"
	"        }\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 指定强制索引\n"
	"     * @access public\n"
	"     * @param string $force 索引名称\n"
	"     * @return $this\n"
	"     */\n"
	"    public function force($force)\n"
	"    {\n"
	"        $this->options[\'force\'] = $force;\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 查询注释\n"
	"     * @access public\n"
	"     * @param string $comment 注释\n"
	"     * @return $this\n"
	"     */\n"
	"    public function comment($comment)\n"
	"    {\n"
	"        $this->options[\'comment\'] = $comment;\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 获取执行的SQL语句\n"
	"     * @access public\n"
	"     * @param boolean $fetch 是否返回sql\n"
	"     * @return $this\n"
	"     */\n"
	"    public function fetchSql($fetch = true)\n"
	"    {\n"
	"        $this->options[\'fetch_sql\'] = $fetch;\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 不主动获取数据集\n"
	"     * @access public\n"
	"     * @param bool $pdo 是否返回 PDOStatement 对象\n"
	"     * @return $this\n"
	"     */\n"
	"    public function fetchPdo($pdo = true)\n"
	"    {\n"
	"        $this->options[\'fetch_pdo\'] = $pdo;\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 设置从主服务器读取数据\n"
	"     * @access public\n"
	"     * @return $this\n"
	"     */\n"
	"    public function master()\n"
	"    {\n"
	"        $this->options[\'master\'] = true;\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 设置是否严格检查字段名\n"
	"     * @access public\n"
	"     * @param bool $strict 是否严格检查字段\n"
	"     * @return $this\n"
	"     */\n"
	"    public function strict($strict = true)\n"
	"    {\n"
	"        $this->options[\'strict\'] = $strict;\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 设置查询数据不存在是否抛出异常\n"
	"     * @access public\n"
	"     * @param bool $fail 数据不存在是否抛出异常\n"
	"     * @return $this\n"
	"     */\n"
	"    public function failException($fail = true)\n"
	"    {\n"
	"        $this->options[\'fail\'] = $fail;\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 设置自增序列名\n"
	"     * @access public\n"
	"     * @param string $sequence 自增序列名\n"
	"     * @return $this\n"
	"     */\n"
	"    public function sequence($sequence = null)\n"
	"    {\n"
	"        $this->options[\'sequence\'] = $sequence;\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 指定数据表主键\n"
	"     * @access public\n"
	"     * @param string $pk 主键\n"
	"     * @return $this\n"
	"     */\n"
	"    public function pk($pk)\n"
	"    {\n"
	"        $this->pk = $pk;\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 查询日期或者时间\n"
	"     * @access public\n"
	"     * @param string       $field 日期字段名\n"
	"     * @param string|array $op    比较运算符或者表达式\n"
	"     * @param string|array $range 比较范围\n"
	"     * @return $this\n"
	"     */\n"
	"    public function whereTime($field, $op, $range = null)\n"
	"    {\n"
	"        if (is_null($range)) {\n"
	"            if (is_array($op)) {\n"
	"                $range = $op;\n"
	"            } else {\n"
	"                // 使用日期表达式\n"
	"                switch (strtolower($op)) {\n"
	"                    case \'today\':\n"
	"                    case \'d\':\n"
	"                        $range = [\'today\', \'tomorrow\'];\n"
	"                        break;\n"
	"                    case \'week\':\n"
	"                    case \'w\':\n"
	"                        $range = [\'this week 00:00:00\', \'next week 00:00:00\'];\n"
	"                        break;\n"
	"                    case \'month\':\n"
	"                    case \'m\':\n"
	"                        $range = [\'first Day of this month 00:00:00\', \'first Day of next month 00:00:00\'];\n"
	"                        break;\n"
	"                    case \'year\':\n"
	"                    case \'y\':\n"
	"                        $range = [\'this year 1/1\', \'next year 1/1\'];\n"
	"                        break;\n"
	"                    case \'yesterday\':\n"
	"                        $range = [\'yesterday\', \'today\'];\n"
	"                        break;\n"
	"                    case \'last week\':\n"
	"                        $range = [\'last week 00:00:00\', \'this week 00:00:00\'];\n"
	"                        break;\n"
	"                    case \'last month\':\n"
	"                        $range = [\'first Day of last month 00:00:00\', \'first Day of this month 00:00:00\'];\n"
	"                        break;\n"
	"                    case \'last year\':\n"
	"                        $range = [\'last year 1/1\', \'this year 1/1\'];\n"
	"                        break;\n"
	"                    default:\n"
	"                        $range = $op;\n"
	"                }\n"
	"            }\n"
	"            $op = is_array($range) ? \'between\' : \'>\';\n"
	"        }\n"
	"        $this->where($field, strtolower($op) . \' time\', $range);\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 获取数据表信息\n"
	"     * @access public\n"
	"     * @param mixed  $tableName 数据表名 留空自动获取\n"
	"     * @param string $fetch     获取信息类型 包括 fields type bind pk\n"
	"     * @return mixed\n"
	"     */\n"
	"    public function getTableInfo($tableName = \'\', $fetch = \'\')\n"
	"    {\n"
	"        if (!$tableName) {\n"
	"            $tableName = $this->getTable();\n"
	"        }\n"
	"        if (is_array($tableName)) {\n"
	"            $tableName = key($tableName) ?: current($tableName);\n"
	"        }\n"
	"\n"
	"        if (strpos($tableName, \',\')) {\n"
	"            // 多表不获取字段信息\n"
	"            return false;\n"
	"        } else {\n"
	"            $tableName = $this->parseSqlTable($tableName);\n"
	"        }\n"
	"\n"
	"        // 修正子查询作为表名的问题\n"
	"        if (strpos($tableName, \')\')) {\n"
	"            return [];\n"
	"        }\n"
	"\n"
	"        list($guid) = explode(\' \', $tableName);\n"
	"        $db         = $this->getConfig(\'database\');\n"
	"        if (!isset(self::$info[$db . \'.\' . $guid])) {\n"
	"            if (!strpos($guid, \'.\')) {\n"
	"                $schema = $db . \'.\' . $guid;\n"
	"            } else {\n"
	"                $schema = $guid;\n"
	"            }\n"
	"            // 读取缓存\n"
	"            if (!App::$debug && is_file(RUNTIME_PATH . \'schema/\' . $schema . \'.php\')) {\n"
	"                $info = include RUNTIME_PATH . \'schema/\' . $schema . \'.php\';\n"
	"            } else {\n"
	"                $info = $this->connection->getFields($guid);\n"
	"            }\n"
	"            $fields = array_keys($info);\n"
	"            $bind   = $type   = [];\n"
	"            foreach ($info as $key => $val) {\n"
	"                // 记录字段类型\n"
	"                $type[$key] = $val[\'type\'];\n"
	"                $bind[$key] = $this->getFieldBindType($val[\'type\']);\n"
	"                if (!empty($val[\'primary\'])) {\n"
	"                    $pk[] = $key;\n"
	"                }\n"
	"            }\n"
	"            if (isset($pk)) {\n"
	"                // 设置主键\n"
	"                $pk = count($pk) > 1 ? $pk : $pk[0];\n"
	"            } else {\n"
	"                $pk = null;\n"
	"            }\n"
	"            self::$info[$db . \'.\' . $guid] = [\'fields\' => $fields, \'type\' => $type, \'bind\' => $bind, \'pk\' => $pk];\n"
	"        }\n"
	"        return $fetch ? self::$info[$db . \'.\' . $guid][$fetch] : self::$info[$db . \'.\' . $guid];\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 获取当前数据表的主键\n"
	"     * @access public\n"
	"     * @param string|array $options 数据表名或者查询参数\n"
	"     * @return string|array\n"
	"     */\n"
	"    public function getPk($options = \'\')\n"
	"    {\n"
	"        if (!empty($this->pk)) {\n"
	"            $pk = $this->pk;\n"
	"        } else {\n"
	"            $pk = $this->getTableInfo(is_array($options) ? $options[\'table\'] : $options, \'pk\');\n"
	"        }\n"
	"        return $pk;\n"
	"    }\n"
	"\n"
	"    // 获取当前数据表字段信息\n"
	"    public function getTableFields($table = \'\')\n"
	"    {\n"
	"        return $this->getTableInfo($table ?: $this->getOptions(\'table\'), \'fields\');\n"
	"    }\n"
	"\n"
	"    // 获取当前数据表字段类型\n"
	"    public function getFieldsType($table = \'\')\n"
	"    {\n"
	"        return $this->getTableInfo($table ?: $this->getOptions(\'table\'), \'type\');\n"
	"    }\n"
	"\n"
	"    // 获取当前数据表绑定信息\n"
	"    public function getFieldsBind($table = \'\')\n"
	"    {\n"
	"        $types = $this->getFieldsType($table);\n"
	"        $bind  = [];\n"
	"        if ($types) {\n"
	"            foreach ($types as $key => $type) {\n"
	"                $bind[$key] = $this->getFieldBindType($type);\n"
	"            }\n"
	"        }\n"
	"        return $bind;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 获取字段绑定类型\n"
	"     * @access public\n"
	"     * @param string $type 字段类型\n"
	"     * @return integer\n"
	"     */\n"
	"    protected function getFieldBindType($type)\n"
	"    {\n"
	"        if (0 === strpos($type, \'set\') || 0 === strpos($type, \'enum\')) {\n"
	"            $bind = PDO::PARAM_STR;\n"
	"        } elseif (preg_match(\'/(int|double|float|decimal|real|numeric|serial|bit)/is\', $type)) {\n"
	"            $bind = PDO::PARAM_INT;\n"
	"        } elseif (preg_match(\'/bool/is\', $type)) {\n"
	"            $bind = PDO::PARAM_BOOL;\n"
	"        } else {\n"
	"            $bind = PDO::PARAM_STR;\n"
	"        }\n"
	"        return $bind;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 参数绑定\n"
	"     * @access public\n"
	"     * @param mixed   $key   参数名\n"
	"     * @param mixed   $value 绑定变量值\n"
	"     * @param integer $type  绑定类型\n"
	"     * @return $this\n"
	"     */\n"
	"    public function bind($key, $value = false, $type = PDO::PARAM_STR)\n"
	"    {\n"
	"        if (is_array($key)) {\n"
	"            $this->bind = array_merge($this->bind, $key);\n"
	"        } else {\n"
	"            $this->bind[$key] = [$value, $type];\n"
	"        }\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 检测参数是否已经绑定\n"
	"     * @access public\n"
	"     * @param string $key 参数名\n"
	"     * @return bool\n"
	"     */\n"
	"    public function isBind($key)\n"
	"    {\n"
	"        return isset($this->bind[$key]);\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 查询参数赋值\n"
	"     * @access protected\n"
	"     * @param array $options 表达式参数\n"
	"     * @return $this\n"
	"     */\n"
	"    protected function options(array $options)\n"
	"    {\n"
	"        $this->options = $options;\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 获取当前的查询参数\n"
	"     * @access public\n"
	"     * @param string $name 参数名\n"
	"     * @return mixed\n"
	"     */\n"
	"    public function getOptions($name = \'\')\n"
	"    {\n"
	"        if (\'\' === $name) {\n"
	"            return $this->options;\n"
	"        } else {\n"
	"            return isset($this->options[$name]) ? $this->options[$name] : null;\n"
	"        }\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 设置关联查询JOIN预查询\n"
	"     * @access public\n"
	"     * @param string|array $with 关联方法名称\n"
	"     * @return $this\n"
	"     */\n"
	"    public function with($with)\n"
	"    {\n"
	"        if (empty($with)) {\n"
	"            return $this;\n"
	"        }\n"
	"\n"
	"        if (is_string($with)) {\n"
	"            $with = explode(\',\', $with);\n"
	"        }\n"
	"\n"
	"        $first = true;\n"
	"\n"
	"        /** @var Model $class */\n"
	"        $class = $this->model;\n"
	"        foreach ($with as $key => $relation) {\n"
	"            $subRelation = \'\';\n"
	"            $closure     = false;\n"
	"            if ($relation instanceof \\Closure) {\n"
	"                // 支持闭包查询过滤关联条件\n"
	"                $closure    = $relation;\n"
	"                $relation   = $key;\n"
	"                $with[$key] = $key;\n"
	"            } elseif (is_array($relation)) {\n"
	"                $subRelation = $relation;\n"
	"                $relation    = $key;\n"
	"            } elseif (is_string($relation) && strpos($relation, \'.\')) {\n"
	"                $with[$key]                   = $relation;\n"
	"                list($relation, $subRelation) = explode(\'.\', $relation, 2);\n"
	"            }\n"
	"\n"
	"            /** @var Relation $model */\n"
	"            $relation = Loader::parseName($relation, 1, false);\n"
	"            $model    = $class->$relation();\n"
	"            if ($model instanceof OneToOne && 0 == $model->getEagerlyType()) {\n"
	"                $model->eagerly($this, $relation, $subRelation, $closure, $first);\n"
	"                $first = false;\n"
	"            } elseif ($closure) {\n"
	"                $with[$key] = $closure;\n"
	"            }\n"
	"        }\n"
	"        $this->via();\n"
	"        if (isset($this->options[\'with\'])) {\n"
	"            $this->options[\'with\'] = array_merge($this->options[\'with\'], $with);\n"
	"        } else {\n"
	"            $this->options[\'with\'] = $with;\n"
	"        }\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 关联统计\n"
	"     * @access public\n"
	"     * @param string|array $relation 关联方法名\n"
	"     * @param bool         $subQuery 是否使用子查询\n"
	"     * @return $this\n"
	"     */\n"
	"    public function withCount($relation, $subQuery = true)\n"
	"    {\n"
	"        if (!$subQuery) {\n"
	"            $this->options[\'with_count\'] = $relation;\n"
	"        } else {\n"
	"            $relations = is_string($relation) ? explode(\',\', $relation) : $relation;\n"
	"            if (!isset($this->options[\'field\'])) {\n"
	"                $this->field(\'*\');\n"
	"            }\n"
	"            foreach ($relations as $key => $relation) {\n"
	"                $closure = $name = null;\n"
	"                if ($relation instanceof \\Closure) {\n"
	"                    $closure  = $relation;\n"
	"                    $relation = $key;\n"
	"                } elseif (!is_int($key)) {\n"
	"                    $name     = $relation;\n"
	"                    $relation = $key;\n"
	"                }\n"
	"                $relation = Loader::parseName($relation, 1, false);\n"
	"\n"
	"                $count = \'(\' . $this->model->$relation()->getRelationCountQuery($closure, $name) . \')\';\n"
	"\n"
	"                if (empty($name)) {\n"
	"                    $name = Loader::parseName($relation) . \'_count\';\n"
	"                }\n"
	"\n"
	"                $this->field([$count => $name]);\n"
	"            }\n"
	"        }\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 关联预加载中 获取关联指定字段值\n"
	"     * example:\n"
	"     * Model::with([\'relation\' => function($query){\n"
	"     *     $query->withField(\"id,name\");\n"
	"     * }])\n"
	"     *\n"
	"     * @param string | array $field 指定获取的字段\n"
	"     * @return $this\n"
	"     */\n"
	"    public function withField($field)\n"
	"    {\n"
	"        $this->options[\'with_field\'] = $field;\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 设置当前字段添加的表别名\n"
	"     * @access public\n"
	"     * @param string $via\n"
	"     * @return $this\n"
	"     */\n"
	"    public function via($via = \'\')\n"
	"    {\n"
	"        $this->options[\'via\'] = $via;\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 设置关联查询\n"
	"     * @access public\n"
	"     * @param string|array $relation 关联名称\n"
	"     * @return $this\n"
	"     */\n"
	"    public function relation($relation)\n"
	"    {\n"
	"        if (empty($relation)) {\n"
	"            return $this;\n"
	"        }\n"
	"        if (is_string($relation)) {\n"
	"            $relation = explode(\',\', $relation);\n"
	"        }\n"
	"        if (isset($this->options[\'relation\'])) {\n"
	"            $this->options[\'relation\'] = array_merge($this->options[\'relation\'], $relation);\n"
	"        } else {\n"
	"            $this->options[\'relation\'] = $relation;\n"
	"        }\n"
	"        return $this;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 把主键值转换为查询条件 支持复合主键\n"
	"     * @access public\n"
	"     * @param array|string $data    主键数据\n"
	"     * @param mixed        $options 表达式参数\n"
	"     * @return void\n"
	"     * @throws Exception\n"
	"     */\n"
	"    protected function parsePkWhere($data, &$options)\n"
	"    {\n"
	"        $pk = $this->getPk($options);\n"
	"        // 获取当前数据表\n"
	"        $table = is_array($options[\'table\']) ? key($options[\'table\']) : $options[\'table\'];\n"
	"        if (!empty($options[\'alias\'][$table])) {\n"
	"            $alias = $options[\'alias\'][$table];\n"
	"        }\n"
	"        if (is_string($pk)) {\n"
	"            $key = isset($alias) ? $alias . \'.\' . $pk : $pk;\n"
	"            // 根据主键查询\n"
	"            if (is_array($data)) {\n"
	"                $where[$key] = isset($data[$pk]) ? $data[$pk] : [\'in\', $data];\n"
	"            } else {\n"
	"                $where[$key] = strpos($data, \',\') ? [\'IN\', $data] : $data;\n"
	"            }\n"
	"        } elseif (is_array($pk) && is_array($data) && !empty($data)) {\n"
	"            // 根据复合主键查询\n"
	"            foreach ($pk as $key) {\n"
	"                if (isset($data[$key])) {\n"
	"                    $attr         = isset($alias) ? $alias . \'.\' . $key : $key;\n"
	"                    $where[$attr] = $data[$key];\n"
	"                } else {\n"
	"                    throw new Exception(\'miss complex primary data\');\n"
	"                }\n"
	"            }\n"
	"        }\n"
	"\n"
	"        if (!empty($where)) {\n"
	"            if (isset($options[\'where\'][\'AND\'])) {\n"
	"                $options[\'where\'][\'AND\'] = array_merge($options[\'where\'][\'AND\'], $where);\n"
	"            } else {\n"
	"                $options[\'where\'][\'AND\'] = $where;\n"
	"            }\n"
	"        }\n"
	"        return;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 插入记录\n"
	"     * @access public\n"
	"     * @param mixed   $data         数据\n"
	"     * @param boolean $replace      是否replace\n"
	"     * @param boolean $getLastInsID 返回自增主键\n"
	"     * @param string  $sequence     自增序列名\n"
	"     * @return integer|string\n"
	"     */\n"
	"    public function insert(array $data = [], $replace = false, $getLastInsID = false, $sequence = null)\n"
	"    {\n"
	"        // 分析查询表达式\n"
	"        $options = $this->parseExpress();\n"
	"        $data    = array_merge($options[\'data\'], $data);\n"
	"        // 生成SQL语句\n"
	"        $sql = $this->builder->insert($data, $options, $replace);\n"
	"        // 获取参数绑定\n"
	"        $bind = $this->getBind();\n"
	"        if ($options[\'fetch_sql\']) {\n"
	"            // 获取实际执行的SQL语句\n"
	"            return $this->connection->getRealSql($sql, $bind);\n"
	"        }\n"
	"\n"
	"        // 执行操作\n"
	"        $result = 0 === $sql ? 0 : $this->execute($sql, $bind, $this);\n"
	"        if ($result) {\n"
	"            $sequence  = $sequence ?: (isset($options[\'sequence\']) ? $options[\'sequence\'] : null);\n"
	"            $lastInsId = $this->getLastInsID($sequence);\n"
	"            if ($lastInsId) {\n"
	"                $pk = $this->getPk($options);\n"
	"                if (is_string($pk)) {\n"
	"                    $data[$pk] = $lastInsId;\n"
	"                }\n"
	"            }\n"
	"            $options[\'data\'] = $data;\n"
	"            $this->trigger(\'after_insert\', $options);\n"
	"\n"
	"            if ($getLastInsID) {\n"
	"                return $lastInsId;\n"
	"            }\n"
	"        }\n"
	"        return $result;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 插入记录并获取自增ID\n"
	"     * @access public\n"
	"     * @param mixed   $data     数据\n"
	"     * @param boolean $replace  是否replace\n"
	"     * @param string  $sequence 自增序列名\n"
	"     * @return integer|string\n"
	"     */\n"
	"    public function insertGetId(array $data, $replace = false, $sequence = null)\n"
	"    {\n"
	"        return $this->insert($data, $replace, true, $sequence);\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 批量插入记录\n"
	"     * @access public\n"
	"     * @param mixed     $dataSet 数据集\n"
	"     * @param boolean   $replace  是否replace\n"
	"     * @param integer   $limit   每次写入数据限制\n"
	"     * @return integer|string\n"
	"     */\n"
	"    public function insertAll(array $dataSet, $replace = false, $limit = null)\n"
	"    {\n"
	"        // 分析查询表达式\n"
	"        $options = $this->parseExpress();\n"
	"        if (!is_array(reset($dataSet))) {\n"
	"            return false;\n"
	"        }\n"
	"\n"
	"        // 生成SQL语句\n"
	"        if (is_null($limit)) {\n"
	"            $sql = $this->builder->insertAll($dataSet, $options, $replace);\n"
	"        } else {\n"
	"            $array = array_chunk($dataSet, $limit, true);\n"
	"            foreach ($array as $item) {\n"
	"                $sql[] = $this->builder->insertAll($item, $options, $replace);\n"
	"            }\n"
	"        }\n"
	"\n"
	"        // 获取参数绑定\n"
	"        $bind = $this->getBind();\n"
	"        if ($options[\'fetch_sql\']) {\n"
	"            // 获取实际执行的SQL语句\n"
	"            return $this->connection->getRealSql($sql, $bind);\n"
	"        } elseif (is_array($sql)) {\n"
	"            // 执行操作\n"
	"            return $this->batchQuery($sql, $bind, $this);\n"
	"        } else {\n"
	"            // 执行操作\n"
	"            return $this->execute($sql, $bind, $this);\n"
	"        }\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 通过Select方式插入记录\n"
	"     * @access public\n"
	"     * @param string $fields 要插入的数据表字段名\n"
	"     * @param string $table  要插入的数据表名\n"
	"     * @return integer|string\n"
	"     * @throws PDOException\n"
	"     */\n"
	"    public function selectInsert($fields, $table)\n"
	"    {\n"
	"        // 分析查询表达式\n"
	"        $options = $this->parseExpress();\n"
	"        // 生成SQL语句\n"
	"        $table = $this->parseSqlTable($table);\n"
	"        $sql   = $this->builder->selectInsert($fields, $table, $options);\n"
	"        // 获取参数绑定\n"
	"        $bind = $this->getBind();\n"
	"        if ($options[\'fetch_sql\']) {\n"
	"            // 获取实际执行的SQL语句\n"
	"            return $this->connection->getRealSql($sql, $bind);\n"
	"        } else {\n"
	"            // 执行操作\n"
	"            return $this->execute($sql, $bind, $this);\n"
	"        }\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 更新记录\n"
	"     * @access public\n"
	"     * @param mixed $data 数据\n"
	"     * @return integer|string\n"
	"     * @throws Exception\n"
	"     * @throws PDOException\n"
	"     */\n"
	"    public function update(array $data = [])\n"
	"    {\n"
	"        $options = $this->parseExpress();\n"
	"        $data    = array_merge($options[\'data\'], $data);\n"
	"        $pk      = $this->getPk($options);\n"
	"        if (isset($options[\'cache\']) && is_string($options[\'cache\'][\'key\'])) {\n"
	"            $key = $options[\'cache\'][\'key\'];\n"
	"        }\n"
	"\n"
	"        if (empty($options[\'where\'])) {\n"
	"            // 如果存在主键数据 则自动作为更新条件\n"
	"            if (is_string($pk) && isset($data[$pk])) {\n"
	"                $where[$pk] = $data[$pk];\n"
	"                if (!isset($key)) {\n"
	"                    $key = \'think:\' . $options[\'table\'] . \'|\' . $data[$pk];\n"
	"                }\n"
	"                unset($data[$pk]);\n"
	"            } elseif (is_array($pk)) {\n"
	"                // 增加复合主键支持\n"
	"                foreach ($pk as $field) {\n"
	"                    if (isset($data[$field])) {\n"
	"                        $where[$field] = $data[$field];\n"
	"                    } else {\n"
	"                        // 如果缺少复合主键数据则不执行\n"
	"                        throw new Exception(\'miss complex primary data\');\n"
	"                    }\n"
	"                    unset($data[$field]);\n"
	"                }\n"
	"            }\n"
	"            if (!isset($where)) {\n"
	"                // 如果没有任何更新条件则不执行\n"
	"                throw new Exception(\'miss update condition\');\n"
	"            } else {\n"
	"                $options[\'where\'][\'AND\'] = $where;\n"
	"            }\n"
	"        } elseif (!isset($key) && is_string($pk) && isset($options[\'where\'][\'AND\'][$pk])) {\n"
	"            $key = $this->getCacheKey($options[\'where\'][\'AND\'][$pk], $options, $this->bind);\n"
	"        }\n"
	"\n"
	"        // 生成UPDATE SQL语句\n"
	"        $sql = $this->builder->update($data, $options);\n"
	"        // 获取参数绑定\n"
	"        $bind = $this->getBind();\n"
	"        if ($options[\'fetch_sql\']) {\n"
	"            // 获取实际执行的SQL语句\n"
	"            return $this->connection->getRealSql($sql, $bind);\n"
	"        } else {\n"
	"            // 检测缓存\n"
	"            if (isset($key) && Cache::get($key)) {\n"
	"                // 删除缓存\n"
	"                Cache::rm($key);\n"
	"            } elseif (!empty($options[\'cache\'][\'tag\'])) {\n"
	"                Cache::clear($options[\'cache\'][\'tag\']);\n"
	"            }\n"
	"            // 执行操作\n"
	"            $result = \'\' == $sql ? 0 : $this->execute($sql, $bind, $this);\n"
	"            if ($result) {\n"
	"                if (is_string($pk) && isset($where[$pk])) {\n"
	"                    $data[$pk] = $where[$pk];\n"
	"                } elseif (is_string($pk) && isset($key) && strpos($key, \'|\')) {\n"
	"                    list($a, $val) = explode(\'|\', $key);\n"
	"                    $data[$pk]     = $val;\n"
	"                }\n"
	"                $options[\'data\'] = $data;\n"
	"                $this->trigger(\'after_update\', $options);\n"
	"            }\n"
	"            return $result;\n"
	"        }\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 执行查询但只返回PDOStatement对象\n"
	"     * @access public\n"
	"     * @return \\PDOStatement|string\n"
	"     */\n"
	"    public function getPdo()\n"
	"    {\n"
	"        // 分析查询表达式\n"
	"        $options = $this->parseExpress();\n"
	"        // 生成查询SQL\n"
	"        $sql = $this->builder->select($options);\n"
	"        // 获取参数绑定\n"
	"        $bind = $this->getBind();\n"
	"        if ($options[\'fetch_sql\']) {\n"
	"            // 获取实际执行的SQL语句\n"
	"            return $this->connection->getRealSql($sql, $bind);\n"
	"        }\n"
	"        // 执行查询操作\n"
	"        return $this->query($sql, $bind, $options[\'master\'], true);\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 查找记录\n"
	"     * @access public\n"
	"     * @param array|string|Query|\\Closure $data\n"
	"     * @return Collection|false|\\PDOStatement|string\n"
	"     * @throws DbException\n"
	"     * @throws ModelNotFoundException\n"
	"     * @throws DataNotFoundException\n"
	"     */\n"
	"    public function select($data = null)\n"
	"    {\n"
	"        if ($data instanceof Query) {\n"
	"            return $data->select();\n"
	"        } elseif ($data instanceof \\Closure) {\n"
	"            call_user_func_array($data, [ & $this]);\n"
	"            $data = null;\n"
	"        }\n"
	"        // 分析查询表达式\n"
	"        $options = $this->parseExpress();\n"
	"\n"
	"        if (false === $data) {\n"
	"            // 用于子查询 不查询只返回SQL\n"
	"            $options[\'fetch_sql\'] = true;\n"
	"        } elseif (!is_null($data)) {\n"
	"            // 主键条件分析\n"
	"            $this->parsePkWhere($data, $options);\n"
	"        }\n"
	"\n"
	"        $resultSet = false;\n"
	"        if (empty($options[\'fetch_sql\']) && !empty($options[\'cache\'])) {\n"
	"            // 判断查询缓存\n"
	"            $cache = $options[\'cache\'];\n"
	"            unset($options[\'cache\']);\n"
	"            $key       = is_string($cache[\'key\']) ? $cache[\'key\'] : md5($this->connection->getConfig(\'database\') . \'.\' . serialize($options) . serialize($this->bind));\n"
	"            $resultSet = Cache::get($key);\n"
	"        }\n"
	"        if (false === $resultSet) {\n"
	"            // 生成查询SQL\n"
	"            $sql = $this->builder->select($options);\n"
	"            // 获取参数绑定\n"
	"            $bind = $this->getBind();\n"
	"            if ($options[\'fetch_sql\']) {\n"
	"                // 获取实际执行的SQL语句\n"
	"                return $this->connection->getRealSql($sql, $bind);\n"
	"            }\n"
	"\n"
	"            $options[\'data\'] = $data;\n"
	"            if ($resultSet = $this->trigger(\'before_select\', $options)) {\n"
	"            } else {\n"
	"                // 执行查询操作\n"
	"                $resultSet = $this->query($sql, $bind, $options[\'master\'], $options[\'fetch_pdo\']);\n"
	"\n"
	"                if ($resultSet instanceof \\PDOStatement) {\n"
	"                    // 返回PDOStatement对象\n"
	"                    return $resultSet;\n"
	"                }\n"
	"            }\n"
	"\n"
	"            if (isset($cache) && false !== $resultSet) {\n"
	"                // 缓存数据集\n"
	"                $this->cacheData($key, $resultSet, $cache);\n"
	"            }\n"
	"        }\n"
	"\n"
	"        // 数据列表读取后的处理\n"
	"        if (!empty($this->model)) {\n"
	"            // 生成模型对象\n"
	"            if (count($resultSet) > 0) {\n"
	"                foreach ($resultSet as $key => $result) {\n"
	"                    /** @var Model $model */\n"
	"                    $model = $this->model->newInstance($result);\n"
	"                    $model->isUpdate(true);\n"
	"\n"
	"                    // 关联查询\n"
	"                    if (!empty($options[\'relation\'])) {\n"
	"                        $model->relationQuery($options[\'relation\']);\n"
	"                    }\n"
	"                    // 关联统计\n"
	"                    if (!empty($options[\'with_count\'])) {\n"
	"                        $model->relationCount($model, $options[\'with_count\']);\n"
	"                    }\n"
	"                    $resultSet[$key] = $model;\n"
	"                }\n"
	"                if (!empty($options[\'with\'])) {\n"
	"                    // 预载入\n"
	"                    $model->eagerlyResultSet($resultSet, $options[\'with\']);\n"
	"                }\n"
	"                // 模型数据集转换\n"
	"                $resultSet = $model->toCollection($resultSet);\n"
	"            } else {\n"
	"                $resultSet = $this->model->toCollection($resultSet);\n"
	"            }\n"
	"        } elseif (\'collection\' == $this->connection->getConfig(\'resultset_type\')) {\n"
	"            // 返回Collection对象\n"
	"            $resultSet = new Collection($resultSet);\n"
	"        }\n"
	"        // 返回结果处理\n"
	"        if (!empty($options[\'fail\']) && count($resultSet) == 0) {\n"
	"            $this->throwNotFound($options);\n"
	"        }\n"
	"        return $resultSet;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 缓存数据\n"
	"     * @access public\n"
	"     * @param string    $key    缓存标识\n"
	"     * @param mixed     $data   缓存数据\n"
	"     * @param array     $config 缓存参数\n"
	"     */\n"
	"    protected function cacheData($key, $data, $config = [])\n"
	"    {\n"
	"        if (isset($config[\'tag\'])) {\n"
	"            Cache::tag($config[\'tag\'])->set($key, $data, $config[\'expire\']);\n"
	"        } else {\n"
	"            Cache::set($key, $data, $config[\'expire\']);\n"
	"        }\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 生成缓存标识\n"
	"     * @access public\n"
	"     * @param mixed     $value   缓存数据\n"
	"     * @param array     $options 缓存参数\n"
	"     * @param array     $bind    绑定参数\n"
	"     * @return string\n"
	"     */\n"
	"    protected function getCacheKey($value, $options, $bind = [])\n"
	"    {\n"
	"        if (is_scalar($value)) {\n"
	"            $data = $value;\n"
	"        } elseif (is_array($value) && is_string($value[0]) && \'eq\' == strtolower($value[0])) {\n"
	"            $data = $value[1];\n"
	"        }\n"
	"        $prefix = $this->connection->getConfig(\'database\') . \'.\';\n"
	"\n"
	"        if (isset($data)) {\n"
	"            return \'think:\' . $prefix . (is_array($options[\'table\']) ? key($options[\'table\']) : $options[\'table\']) . \'|\' . $data;\n"
	"        }\n"
	"\n"
	"        try {\n"
	"            return md5($prefix . serialize($options) . serialize($bind));\n"
	"        } catch (\\Exception $e) {\n"
	"            throw new Exception(\'closure not support cache(true)\');\n"
	"        }\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 查找单条记录\n"
	"     * @access public\n"
	"     * @param array|string|Query|\\Closure $data\n"
	"     * @return array|false|\\PDOStatement|string|Model\n"
	"     * @throws DbException\n"
	"     * @throws ModelNotFoundException\n"
	"     * @throws DataNotFoundException\n"
	"     */\n"
	"    public function find($data = null)\n"
	"    {\n"
	"        if ($data instanceof Query) {\n"
	"            return $data->find();\n"
	"        } elseif ($data instanceof \\Closure) {\n"
	"            call_user_func_array($data, [ & $this]);\n"
	"            $data = null;\n"
	"        }\n"
	"        // 分析查询表达式\n"
	"        $options = $this->parseExpress();\n"
	"        $pk      = $this->getPk($options);\n"
	"        if (!is_null($data)) {\n"
	"            // AR模式分析主键条件\n"
	"            $this->parsePkWhere($data, $options);\n"
	"        } elseif (!empty($options[\'cache\']) && true === $options[\'cache\'][\'key\'] && is_string($pk) && isset($options[\'where\'][\'AND\'][$pk])) {\n"
	"            $key = $this->getCacheKey($options[\'where\'][\'AND\'][$pk], $options, $this->bind);\n"
	"        }\n"
	"\n"
	"        $options[\'limit\'] = 1;\n"
	"        $result           = false;\n"
	"        if (empty($options[\'fetch_sql\']) && !empty($options[\'cache\'])) {\n"
	"            // 判断查询缓存\n"
	"            $cache = $options[\'cache\'];\n"
	"            if (true === $cache[\'key\'] && !is_null($data) && !is_array($data)) {\n"
	"                $key = \'think:\' . $this->connection->getConfig(\'database\') . \'.\' . (is_array($options[\'table\']) ? key($options[\'table\']) : $options[\'table\']) . \'|\' . $data;\n"
	"            } elseif (is_string($cache[\'key\'])) {\n"
	"                $key = $cache[\'key\'];\n"
	"            } elseif (!isset($key)) {\n"
	"                $key = md5($this->connection->getConfig(\'database\') . \'.\' . serialize($options) . serialize($this->bind));\n"
	"            }\n"
	"            $result = Cache::get($key);\n"
	"        }\n"
	"        if (false === $result) {\n"
	"            // 生成查询SQL\n"
	"            $sql = $this->builder->select($options);\n"
	"            // 获取参数绑定\n"
	"            $bind = $this->getBind();\n"
	"            if ($options[\'fetch_sql\']) {\n"
	"                // 获取实际执行的SQL语句\n"
	"                return $this->connection->getRealSql($sql, $bind);\n"
	"            }\n"
	"            if (is_string($pk)) {\n"
	"                if (!is_array($data)) {\n"
	"                    if (isset($key) && strpos($key, \'|\')) {\n"
	"                        list($a, $val) = explode(\'|\', $key);\n"
	"                        $item[$pk]     = $val;\n"
	"                    } else {\n"
	"                        $item[$pk] = $data;\n"
	"                    }\n"
	"                    $data = $item;\n"
	"                }\n"
	"            }\n"
	"            $options[\'data\'] = $data;\n"
	"            // 事件回调\n"
	"            if ($result = $this->trigger(\'before_find\', $options)) {\n"
	"            } else {\n"
	"                // 执行查询\n"
	"                $resultSet = $this->query($sql, $bind, $options[\'master\'], $options[\'fetch_pdo\']);\n"
	"\n"
	"                if ($resultSet instanceof \\PDOStatement) {\n"
	"                    // 返回PDOStatement对象\n"
	"                    return $resultSet;\n"
	"                }\n"
	"                $result = isset($resultSet[0]) ? $resultSet[0] : null;\n"
	"            }\n"
	"\n"
	"            if (isset($cache) && $result) {\n"
	"                // 缓存数据\n"
	"                $this->cacheData($key, $result, $cache);\n"
	"            }\n"
	"        }\n"
	"\n"
	"        // 数据处理\n"
	"        if (!empty($result)) {\n"
	"            if (!empty($this->model)) {\n"
	"                // 返回模型对象\n"
	"                $result = $this->model->newInstance($result);\n"
	"                $result->isUpdate(true, isset($options[\'where\'][\'AND\']) ? $options[\'where\'][\'AND\'] : null);\n"
	"                // 关联查询\n"
	"                if (!empty($options[\'relation\'])) {\n"
	"                    $result->relationQuery($options[\'relation\']);\n"
	"                }\n"
	"                // 预载入查询\n"
	"                if (!empty($options[\'with\'])) {\n"
	"                    $result->eagerlyResult($result, $options[\'with\']);\n"
	"                }\n"
	"                // 关联统计\n"
	"                if (!empty($options[\'with_count\'])) {\n"
	"                    $result->relationCount($result, $options[\'with_count\']);\n"
	"                }\n"
	"            }\n"
	"        } elseif (!empty($options[\'fail\'])) {\n"
	"            $this->throwNotFound($options);\n"
	"        }\n"
	"        return $result;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 查询失败 抛出异常\n"
	"     * @access public\n"
	"     * @param array $options 查询参数\n"
	"     * @throws ModelNotFoundException\n"
	"     * @throws DataNotFoundException\n"
	"     */\n"
	"    protected function throwNotFound($options = [])\n"
	"    {\n"
	"        if (!empty($this->model)) {\n"
	"            $class = get_class($this->model);\n"
	"            throw new ModelNotFoundException(\'model data Not Found:\' . $class, $class, $options);\n"
	"        } else {\n"
	"            $table = is_array($options[\'table\']) ? key($options[\'table\']) : $options[\'table\'];\n"
	"            throw new DataNotFoundException(\'table data not Found:\' . $table, $table, $options);\n"
	"        }\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 查找多条记录 如果不存在则抛出异常\n"
	"     * @access public\n"
	"     * @param array|string|Query|\\Closure $data\n"
	"     * @return array|\\PDOStatement|string|Model\n"
	"     * @throws DbException\n"
	"     * @throws ModelNotFoundException\n"
	"     * @throws DataNotFoundException\n"
	"     */\n"
	"    public function selectOrFail($data = null)\n"
	"    {\n"
	"        return $this->failException(true)->select($data);\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 查找单条记录 如果不存在则抛出异常\n"
	"     * @access public\n"
	"     * @param array|string|Query|\\Closure $data\n"
	"     * @return array|\\PDOStatement|string|Model\n"
	"     * @throws DbException\n"
	"     * @throws ModelNotFoundException\n"
	"     * @throws DataNotFoundException\n"
	"     */\n"
	"    public function findOrFail($data = null)\n"
	"    {\n"
	"        return $this->failException(true)->find($data);\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 分批数据返回处理\n"
	"     * @access public\n"
	"     * @param integer  $count    每次处理的数据数量\n"
	"     * @param callable $callback 处理回调方法\n"
	"     * @param string   $column   分批处理的字段名\n"
	"     * @param string   $order    排序规则\n"
	"     * @return boolean\n"
	"     * @throws \\LogicException\n"
	"     */\n"
	"    public function chunk($count, $callback, $column = null, $order = \'asc\')\n"
	"    {\n"
	"        $options = $this->getOptions();\n"
	"        if (empty($options[\'table\'])) {\n"
	"            $options[\'table\'] = $this->getTable();\n"
	"        }\n"
	"        $column = $column ?: $this->getPk($options);\n"
	"\n"
	"        if (isset($options[\'order\'])) {\n"
	"            if (App::$debug) {\n"
	"                throw new \\LogicException(\'chunk not support call order\');\n"
	"            }\n"
	"            unset($options[\'order\']);\n"
	"        }\n"
	"        $bind = $this->bind;\n"
	"        if (is_array($column)) {\n"
	"            $times = 1;\n"
	"            $query = $this->options($options)->page($times, $count);\n"
	"        } else {\n"
	"            if (strpos($column, \'.\')) {\n"
	"                list($alias, $key) = explode(\'.\', $column);\n"
	"            } else {\n"
	"                $key = $column;\n"
	"            }\n"
	"            $query = $this->options($options)->limit($count);\n"
	"        }\n"
	"        $resultSet = $query->order($column, $order)->select();\n"
	"\n"
	"        while (count($resultSet) > 0) {\n"
	"            if ($resultSet instanceof Collection) {\n"
	"                $resultSet = $resultSet->all();\n"
	"            }\n"
	"\n"
	"            if (false === call_user_func($callback, $resultSet)) {\n"
	"                return false;\n"
	"            }\n"
	"\n"
	"            if (is_array($column)) {\n"
	"                $times++;\n"
	"                $query = $this->options($options)->page($times, $count);\n"
	"            } else {\n"
	"                $end    = end($resultSet);\n"
	"                $lastId = is_array($end) ? $end[$key] : $end->getData($key);\n"
	"                $query  = $this->options($options)\n"
	"                    ->limit($count)\n"
	"                    ->where($column, \'asc\' == strtolower($order) ? \'>\' : \'<\', $lastId);\n"
	"            }\n"
	"\n"
	"            $resultSet = $query->bind($bind)->order($column, $order)->select();\n"
	"        }\n"
	"\n"
	"        return true;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 获取绑定的参数 并清空\n"
	"     * @access public\n"
	"     * @return array\n"
	"     */\n"
	"    public function getBind()\n"
	"    {\n"
	"        $bind       = $this->bind;\n"
	"        $this->bind = [];\n"
	"        return $bind;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 创建子查询SQL\n"
	"     * @access public\n"
	"     * @param bool $sub\n"
	"     * @return string\n"
	"     * @throws DbException\n"
	"     */\n"
	"    public function buildSql($sub = true)\n"
	"    {\n"
	"        return $sub ? \'( \' . $this->select(false) . \' )\' : $this->select(false);\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 删除记录\n"
	"     * @access public\n"
	"     * @param mixed $data 表达式 true 表示强制删除\n"
	"     * @return int\n"
	"     * @throws Exception\n"
	"     * @throws PDOException\n"
	"     */\n"
	"    public function delete($data = null)\n"
	"    {\n"
	"        // 分析查询表达式\n"
	"        $options = $this->parseExpress();\n"
	"        $pk      = $this->getPk($options);\n"
	"        if (isset($options[\'cache\']) && is_string($options[\'cache\'][\'key\'])) {\n"
	"            $key = $options[\'cache\'][\'key\'];\n"
	"        }\n"
	"\n"
	"        if (!is_null($data) && true !== $data) {\n"
	"            if (!isset($key) && !is_array($data)) {\n"
	"                // 缓存标识\n"
	"                $key = \'think:\' . $options[\'table\'] . \'|\' . $data;\n"
	"            }\n"
	"            // AR模式分析主键条件\n"
	"            $this->parsePkWhere($data, $options);\n"
	"        } elseif (!isset($key) && is_string($pk) && isset($options[\'where\'][\'AND\'][$pk])) {\n"
	"            $key = $this->getCacheKey($options[\'where\'][\'AND\'][$pk], $options, $this->bind);\n"
	"        }\n"
	"\n"
	"        if (true !== $data && empty($options[\'where\'])) {\n"
	"            // 如果条件为空 不进行删除操作 除非设置 1=1\n"
	"            throw new Exception(\'delete without condition\');\n"
	"        }\n"
	"        // 生成删除SQL语句\n"
	"        $sql = $this->builder->delete($options);\n"
	"        // 获取参数绑定\n"
	"        $bind = $this->getBind();\n"
	"        if ($options[\'fetch_sql\']) {\n"
	"            // 获取实际执行的SQL语句\n"
	"            return $this->connection->getRealSql($sql, $bind);\n"
	"        }\n"
	"\n"
	"        // 检测缓存\n"
	"        if (isset($key) && Cache::get($key)) {\n"
	"            // 删除缓存\n"
	"            Cache::rm($key);\n"
	"        } elseif (!empty($options[\'cache\'][\'tag\'])) {\n"
	"            Cache::clear($options[\'cache\'][\'tag\']);\n"
	"        }\n"
	"        // 执行操作\n"
	"        $result = $this->execute($sql, $bind, $this);\n"
	"        if ($result) {\n"
	"            if (!is_array($data) && is_string($pk) && isset($key) && strpos($key, \'|\')) {\n"
	"                list($a, $val) = explode(\'|\', $key);\n"
	"                $item[$pk]     = $val;\n"
	"                $data          = $item;\n"
	"            }\n"
	"            $options[\'data\'] = $data;\n"
	"            $this->trigger(\'after_delete\', $options);\n"
	"        }\n"
	"        return $result;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 分析表达式（可用于查询或者写入操作）\n"
	"     * @access protected\n"
	"     * @return array\n"
	"     */\n"
	"    protected function parseExpress()\n"
	"    {\n"
	"        $options = $this->options;\n"
	"\n"
	"        // 获取数据表\n"
	"        if (empty($options[\'table\'])) {\n"
	"            $options[\'table\'] = $this->getTable();\n"
	"        }\n"
	"\n"
	"        if (!isset($options[\'where\'])) {\n"
	"            $options[\'where\'] = [];\n"
	"        } elseif (isset($options[\'view\'])) {\n"
	"            // 视图查询条件处理\n"
	"            foreach ([\'AND\', \'OR\'] as $logic) {\n"
	"                if (isset($options[\'where\'][$logic])) {\n"
	"                    foreach ($options[\'where\'][$logic] as $key => $val) {\n"
	"                        if (array_key_exists($key, $options[\'map\'])) {\n"
	"                            $options[\'where\'][$logic][$options[\'map\'][$key]] = $val;\n"
	"                            unset($options[\'where\'][$logic][$key]);\n"
	"                        }\n"
	"                    }\n"
	"                }\n"
	"            }\n"
	"\n"
	"            if (isset($options[\'order\'])) {\n"
	"                // 视图查询排序处理\n"
	"                if (is_string($options[\'order\'])) {\n"
	"                    $options[\'order\'] = explode(\',\', $options[\'order\']);\n"
	"                }\n"
	"                foreach ($options[\'order\'] as $key => $val) {\n"
	"                    if (is_numeric($key)) {\n"
	"                        if (strpos($val, \' \')) {\n"
	"                            list($field, $sort) = explode(\' \', $val);\n"
	"                            if (array_key_exists($field, $options[\'map\'])) {\n"
	"                                $options[\'order\'][$options[\'map\'][$field]] = $sort;\n"
	"                                unset($options[\'order\'][$key]);\n"
	"                            }\n"
	"                        } elseif (array_key_exists($val, $options[\'map\'])) {\n"
	"                            $options[\'order\'][$options[\'map\'][$val]] = \'asc\';\n"
	"                            unset($options[\'order\'][$key]);\n"
	"                        }\n"
	"                    } elseif (array_key_exists($key, $options[\'map\'])) {\n"
	"                        $options[\'order\'][$options[\'map\'][$key]] = $val;\n"
	"                        unset($options[\'order\'][$key]);\n"
	"                    }\n"
	"                }\n"
	"            }\n"
	"        }\n"
	"\n"
	"        if (!isset($options[\'field\'])) {\n"
	"            $options[\'field\'] = \'*\';\n"
	"        }\n"
	"\n"
	"        if (!isset($options[\'data\'])) {\n"
	"            $options[\'data\'] = [];\n"
	"        }\n"
	"\n"
	"        if (!isset($options[\'strict\'])) {\n"
	"            $options[\'strict\'] = $this->getConfig(\'fields_strict\');\n"
	"        }\n"
	"\n"
	"        foreach ([\'master\', \'lock\', \'fetch_pdo\', \'fetch_sql\', \'distinct\'] as $name) {\n"
	"            if (!isset($options[$name])) {\n"
	"                $options[$name] = false;\n"
	"            }\n"
	"        }\n"
	"\n"
	"        if (isset(static::$readMaster[\'*\']) || (is_string($options[\'table\']) && isset(static::$readMaster[$options[\'table\']]))) {\n"
	"            $options[\'master\'] = true;\n"
	"        }\n"
	"\n"
	"        foreach ([\'join\', \'union\', \'group\', \'having\', \'limit\', \'order\', \'force\', \'comment\'] as $name) {\n"
	"            if (!isset($options[$name])) {\n"
	"                $options[$name] = \'\';\n"
	"            }\n"
	"        }\n"
	"\n"
	"        if (isset($options[\'page\'])) {\n"
	"            // 根据页数计算limit\n"
	"            list($page, $listRows) = $options[\'page\'];\n"
	"            $page                  = $page > 0 ? $page : 1;\n"
	"            $listRows              = $listRows > 0 ? $listRows : (is_numeric($options[\'limit\']) ? $options[\'limit\'] : 20);\n"
	"            $offset                = $listRows * ($page - 1);\n"
	"            $options[\'limit\']      = $offset . \',\' . $listRows;\n"
	"        }\n"
	"\n"
	"        $this->options = [];\n"
	"        return $options;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 注册回调方法\n"
	"     * @access public\n"
	"     * @param string   $event    事件名\n"
	"     * @param callable $callback 回调方法\n"
	"     * @return void\n"
	"     */\n"
	"    public static function event($event, $callback)\n"
	"    {\n"
	"        self::$event[$event] = $callback;\n"
	"    }\n"
	"\n"
	"    /**\n"
	"     * 触发事件\n"
	"     * @access protected\n"
	"     * @param string $event   事件名\n"
	"     * @param mixed  $params  额外参数\n"
	"     * @return bool\n"
	"     */\n"
	"    protected function trigger($event, $params = [])\n"
	"    {\n"
	"        $result = false;\n"
	"        if (isset(self::$event[$event])) {\n"
	"            $callback = self::$event[$event];\n"
	"            $result   = call_user_func_array($callback, [$params, $this]);\n"
	"        }\n"
	"        return $result;\n"
	"    }\n"
	"}\n"
	"\n"
;
#endif